Imported Upstream version 2.3.1 upstream/2.3.1
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 14 Feb 2019 08:33:09 +0000 (17:33 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Thu, 14 Feb 2019 08:33:09 +0000 (17:33 +0900)
1395 files changed:
AUTHORS
BUILD.md
CMakeLists.txt
ChangeLog
Makefile.in
NEWS
README
README.python.md
README.wine.md
RELEASING.md
TODO
aclocal.m4
config.guess
config.h.in
config.sub
configure
configure.ac
docs/Makefile.am
docs/Makefile.in
docs/harfbuzz-docs.xml
docs/harfbuzz-sections.txt
docs/harfbuzz.types
docs/html/a-clustering-example-for-levels-0-and-1.html
docs/html/aat-shaping.html [new file with mode: 0644]
docs/html/adding-text-to-the-buffer.html
docs/html/annotation-glossary.html
docs/html/api-index-0-9-10.html
docs/html/api-index-0-9-11.html
docs/html/api-index-0-9-2.html
docs/html/api-index-0-9-20.html
docs/html/api-index-0-9-22.html
docs/html/api-index-0-9-28.html
docs/html/api-index-0-9-30.html
docs/html/api-index-0-9-31.html
docs/html/api-index-0-9-38.html
docs/html/api-index-0-9-39.html
docs/html/api-index-0-9-41.html
docs/html/api-index-0-9-42.html
docs/html/api-index-0-9-5.html
docs/html/api-index-0-9-7.html
docs/html/api-index-0-9-8.html
docs/html/api-index-1-0-5.html
docs/html/api-index-1-1-2.html
docs/html/api-index-1-1-3.html
docs/html/api-index-1-2-3.html
docs/html/api-index-1-3-3.html
docs/html/api-index-1-4-0.html [new file with mode: 0644]
docs/html/api-index-1-4-2.html
docs/html/api-index-1-4-3.html
docs/html/api-index-1-5-0.html
docs/html/api-index-1-6-0.html
docs/html/api-index-1-7-5.html [new file with mode: 0644]
docs/html/api-index-1-7-7.html [new file with mode: 0644]
docs/html/api-index-1-8-0.html [new file with mode: 0644]
docs/html/api-index-1-8-1.html [new file with mode: 0644]
docs/html/api-index-1-8-5.html [new file with mode: 0644]
docs/html/api-index-1-8-6.html [new file with mode: 0644]
docs/html/api-index-1-9-0.html [new file with mode: 0644]
docs/html/api-index-2-0-0.html [new file with mode: 0644]
docs/html/api-index-2-1-0.html [new file with mode: 0644]
docs/html/api-index-full.html
docs/html/buffers-language-script-and-direction.html
docs/html/building.html
docs/html/ch01s03.html [new file with mode: 0644]
docs/html/ch03s02.html [new file with mode: 0644]
docs/html/ch03s03.html [new file with mode: 0644]
docs/html/ch08.html [deleted file]
docs/html/ch09.html [new file with mode: 0644]
docs/html/ch10.html [new file with mode: 0644]
docs/html/ch11.html [new file with mode: 0644]
docs/html/ch12.html [new file with mode: 0644]
docs/html/clusters.html
docs/html/complex-scripts.html [new file with mode: 0644]
docs/html/customizing-unicode-functions.html
docs/html/deprecated-api-index.html
docs/html/fonts-and-faces.html
docs/html/getting-started.html [new file with mode: 0644]
docs/html/graphite-shaping.html [new file with mode: 0644]
docs/html/harfbuzz-Buffers.html [deleted file]
docs/html/harfbuzz-Shaping.html [deleted file]
docs/html/harfbuzz-hb-aat-layout.html [new file with mode: 0644]
docs/html/harfbuzz-hb-blob.html
docs/html/harfbuzz-hb-buffer.html [new file with mode: 0644]
docs/html/harfbuzz-hb-common.html
docs/html/harfbuzz-hb-coretext.html
docs/html/harfbuzz-hb-deprecated.html
docs/html/harfbuzz-hb-face.html
docs/html/harfbuzz-hb-font.html
docs/html/harfbuzz-hb-ft.html
docs/html/harfbuzz-hb-glib.html
docs/html/harfbuzz-hb-gobject.html
docs/html/harfbuzz-hb-graphite2.html
docs/html/harfbuzz-hb-icu.html
docs/html/harfbuzz-hb-map.html [new file with mode: 0644]
docs/html/harfbuzz-hb-ot-color.html [new file with mode: 0644]
docs/html/harfbuzz-hb-ot-font.html
docs/html/harfbuzz-hb-ot-layout.html
docs/html/harfbuzz-hb-ot-math.html
docs/html/harfbuzz-hb-ot-name.html [new file with mode: 0644]
docs/html/harfbuzz-hb-ot-shape.html
docs/html/harfbuzz-hb-ot-tag.html [deleted file]
docs/html/harfbuzz-hb-ot-var.html [new file with mode: 0644]
docs/html/harfbuzz-hb-ot.html [deleted file]
docs/html/harfbuzz-hb-set.html
docs/html/harfbuzz-hb-shape-plan.html
docs/html/harfbuzz-hb-shape.html [new file with mode: 0644]
docs/html/harfbuzz-hb-unicode.html
docs/html/harfbuzz-hb-uniscribe.html
docs/html/harfbuzz-hb-version.html
docs/html/harfbuzz-hb.html [deleted file]
docs/html/harfbuzz.devhelp2
docs/html/hello-harfbuzz.html [deleted file]
docs/html/home.png
docs/html/index.html
docs/html/install-harfbuzz.html
docs/html/left-insensitive.png
docs/html/left.png
docs/html/level-2.html
docs/html/object-tree.html [deleted file]
docs/html/opentype-shaping-models.html [new file with mode: 0644]
docs/html/plans-and-caching.html
docs/html/pt01.html
docs/html/pt02.html
docs/html/reordering-in-levels-0-and-1.html
docs/html/right-insensitive.png
docs/html/right.png
docs/html/setting-buffer-properties.html
docs/html/shaping-and-shape-plans.html
docs/html/shaping-concepts.html [new file with mode: 0644]
docs/html/shaping-operations.html [new file with mode: 0644]
docs/html/style.css
docs/html/text-runs.html [new file with mode: 0644]
docs/html/the-distinction-between-levels-0-and-1.html
docs/html/unicode-character-categories.html [new file with mode: 0644]
docs/html/up-insensitive.png
docs/html/up.png
docs/html/using-harfbuzzs-native-opentype-implementation.html
docs/html/using-your-own-font-functions.html
docs/html/what-about-the-other-scripts.html
docs/html/what-harfbuzz-doesnt-do.html [new file with mode: 0644]
docs/html/what-is-harfbuzz.html
docs/html/why-do-i-need-a-shaping-engine.html [new file with mode: 0644]
docs/html/why-is-it-called-harfbuzz.html
docs/html/working-with-harfbuzz-clusters.html [new file with mode: 0644]
docs/usermanual-buffers-language-script-and-direction.xml
docs/usermanual-clusters.xml
docs/usermanual-fonts-and-faces.xml
docs/usermanual-getting-started.xml [new file with mode: 0644]
docs/usermanual-glyph-information.xml
docs/usermanual-hello-harfbuzz.xml [deleted file]
docs/usermanual-install-harfbuzz.xml
docs/usermanual-opentype-features.xml
docs/usermanual-shaping-concepts.xml [new file with mode: 0644]
docs/usermanual-what-is-harfbuzz.xml
docs/version.xml
gtk-doc.make
m4/pkg.m4 [deleted file]
src/Makefile.am
src/Makefile.in
src/Makefile.sources
src/check-includes.sh
src/check-static-inits.sh
src/check-symbols.sh
src/dump-emoji.cc [deleted file]
src/dump-fon.cc [deleted file]
src/dump-indic-data.cc
src/dump-khmer-data.cc
src/dump-myanmar-data.cc
src/dump-use-data.cc
src/gen-def.py
src/gen-emoji-table.py [new file with mode: 0755]
src/gen-indic-table.py
src/gen-os2-unicode-ranges.py [new file with mode: 0644]
src/gen-tag-table.py [new file with mode: 0755]
src/gen-use-table.py
src/gen-vowel-constraints.py [new file with mode: 0755]
src/harfbuzz-config.cmake.in
src/hb-aat-fdsc-table.hh [new file with mode: 0644]
src/hb-aat-fmtx-table.hh [deleted file]
src/hb-aat-gcid-table.hh [deleted file]
src/hb-aat-layout-ankr-table.hh
src/hb-aat-layout-bsln-table.hh
src/hb-aat-layout-common-private.hh [deleted file]
src/hb-aat-layout-common.hh [new file with mode: 0644]
src/hb-aat-layout-feat-table.hh
src/hb-aat-layout-just-table.hh [new file with mode: 0644]
src/hb-aat-layout-kerx-table.hh
src/hb-aat-layout-lcar-table.hh [new file with mode: 0644]
src/hb-aat-layout-morx-table.hh
src/hb-aat-layout-private.hh [deleted file]
src/hb-aat-layout-trak-table.hh
src/hb-aat-layout.cc
src/hb-aat-layout.h [new file with mode: 0644]
src/hb-aat-layout.hh [new file with mode: 0644]
src/hb-aat-ltag-table.hh
src/hb-aat-map.cc [new file with mode: 0644]
src/hb-aat-map.hh [new file with mode: 0644]
src/hb-aat.h [new file with mode: 0644]
src/hb-array.hh [new file with mode: 0644]
src/hb-atomic-private.hh [deleted file]
src/hb-atomic.hh [new file with mode: 0644]
src/hb-blob-private.hh [deleted file]
src/hb-blob.cc
src/hb-blob.hh [new file with mode: 0644]
src/hb-buffer-deserialize-json.hh
src/hb-buffer-deserialize-json.rl
src/hb-buffer-deserialize-text.hh
src/hb-buffer-deserialize-text.rl
src/hb-buffer-private.hh [deleted file]
src/hb-buffer-serialize.cc
src/hb-buffer.cc
src/hb-buffer.h
src/hb-buffer.hh [new file with mode: 0644]
src/hb-cache.hh [new file with mode: 0644]
src/hb-cff-interp-common.hh [new file with mode: 0644]
src/hb-cff-interp-cs-common.hh [new file with mode: 0644]
src/hb-cff-interp-dict-common.hh [new file with mode: 0644]
src/hb-cff1-interp-cs.hh [new file with mode: 0644]
src/hb-cff2-interp-cs.hh [new file with mode: 0644]
src/hb-common.cc
src/hb-common.h
src/hb-coretext.cc
src/hb-debug.hh
src/hb-deprecated.h
src/hb-directwrite.cc
src/hb-dsalgs.hh
src/hb-face-private.hh [deleted file]
src/hb-face.cc
src/hb-face.h
src/hb-face.hh [new file with mode: 0644]
src/hb-fallback-shape.cc
src/hb-font-private.hh [deleted file]
src/hb-font.cc
src/hb-font.h
src/hb-font.hh [new file with mode: 0644]
src/hb-ft.cc
src/hb-glib.cc
src/hb-gobject-enums.cc.tmpl
src/hb-gobject-enums.h.tmpl
src/hb-gobject-structs.cc
src/hb-gobject-structs.h
src/hb-graphite2.cc
src/hb-graphite2.h
src/hb-icu.cc
src/hb-iter.hh [new file with mode: 0644]
src/hb-kern.hh [new file with mode: 0644]
src/hb-machinery.hh [new file with mode: 0644]
src/hb-map-private.hh [deleted file]
src/hb-map.cc
src/hb-map.hh [new file with mode: 0644]
src/hb-mutex-private.hh [deleted file]
src/hb-mutex.hh [new file with mode: 0644]
src/hb-null.hh [new file with mode: 0644]
src/hb-object-private.hh [deleted file]
src/hb-object.hh [new file with mode: 0644]
src/hb-open-file-private.hh [deleted file]
src/hb-open-file.hh [new file with mode: 0644]
src/hb-open-type-private.hh [deleted file]
src/hb-open-type.hh [new file with mode: 0644]
src/hb-ot-cff-common.hh [new file with mode: 0644]
src/hb-ot-cff1-table.cc [new file with mode: 0644]
src/hb-ot-cff1-table.hh [new file with mode: 0644]
src/hb-ot-cff2-table.cc [new file with mode: 0644]
src/hb-ot-cff2-table.hh [new file with mode: 0644]
src/hb-ot-cmap-table.hh
src/hb-ot-color-cbdt-table.hh
src/hb-ot-color-colr-table.hh
src/hb-ot-color-cpal-table.hh
src/hb-ot-color-sbix-table.hh
src/hb-ot-color-svg-table.hh
src/hb-ot-color.cc
src/hb-ot-color.h [new file with mode: 0644]
src/hb-ot-deprecated.h [new file with mode: 0644]
src/hb-ot-face.cc [new file with mode: 0644]
src/hb-ot-face.hh [new file with mode: 0644]
src/hb-ot-font.cc
src/hb-ot-gasp-table.hh [new file with mode: 0644]
src/hb-ot-glyf-table.hh
src/hb-ot-hdmx-table.hh
src/hb-ot-head-table.hh
src/hb-ot-hhea-table.hh
src/hb-ot-hmtx-table.hh
src/hb-ot-kern-table.hh
src/hb-ot-layout-base-table.hh
src/hb-ot-layout-common-private.hh [deleted file]
src/hb-ot-layout-common.hh [new file with mode: 0644]
src/hb-ot-layout-gdef-table.hh
src/hb-ot-layout-gpos-table.hh
src/hb-ot-layout-gsub-table.hh
src/hb-ot-layout-gsubgpos-private.hh [deleted file]
src/hb-ot-layout-gsubgpos.hh [new file with mode: 0644]
src/hb-ot-layout-jstf-table.hh
src/hb-ot-layout-private.hh [deleted file]
src/hb-ot-layout.cc
src/hb-ot-layout.h
src/hb-ot-layout.hh [new file with mode: 0644]
src/hb-ot-map-private.hh [deleted file]
src/hb-ot-map.cc
src/hb-ot-map.hh [new file with mode: 0644]
src/hb-ot-math-table.hh
src/hb-ot-math.cc
src/hb-ot-maxp-table.hh
src/hb-ot-name-language.cc [new file with mode: 0644]
src/hb-ot-name-language.hh [new file with mode: 0644]
src/hb-ot-name-table.hh
src/hb-ot-name.cc [new file with mode: 0644]
src/hb-ot-name.h [new file with mode: 0644]
src/hb-ot-os2-table.hh
src/hb-ot-os2-unicode-ranges.hh
src/hb-ot-post-macroman.hh
src/hb-ot-post-table.hh
src/hb-ot-shape-complex-arabic-fallback.hh
src/hb-ot-shape-complex-arabic-private.hh [deleted file]
src/hb-ot-shape-complex-arabic-win1256.hh
src/hb-ot-shape-complex-arabic.cc
src/hb-ot-shape-complex-arabic.hh [new file with mode: 0644]
src/hb-ot-shape-complex-default.cc
src/hb-ot-shape-complex-hangul.cc
src/hb-ot-shape-complex-hebrew.cc
src/hb-ot-shape-complex-indic-machine.hh
src/hb-ot-shape-complex-indic-machine.rl
src/hb-ot-shape-complex-indic-private.hh [deleted file]
src/hb-ot-shape-complex-indic-table.cc
src/hb-ot-shape-complex-indic.cc
src/hb-ot-shape-complex-indic.hh [new file with mode: 0644]
src/hb-ot-shape-complex-khmer-machine.hh
src/hb-ot-shape-complex-khmer-machine.rl
src/hb-ot-shape-complex-khmer-private.hh [deleted file]
src/hb-ot-shape-complex-khmer.cc
src/hb-ot-shape-complex-khmer.hh [new file with mode: 0644]
src/hb-ot-shape-complex-myanmar-machine.hh
src/hb-ot-shape-complex-myanmar-machine.rl
src/hb-ot-shape-complex-myanmar-private.hh [deleted file]
src/hb-ot-shape-complex-myanmar.cc
src/hb-ot-shape-complex-myanmar.hh [new file with mode: 0644]
src/hb-ot-shape-complex-private.hh [deleted file]
src/hb-ot-shape-complex-thai.cc
src/hb-ot-shape-complex-tibetan.cc [deleted file]
src/hb-ot-shape-complex-use-machine.hh
src/hb-ot-shape-complex-use-machine.rl
src/hb-ot-shape-complex-use-private.hh [deleted file]
src/hb-ot-shape-complex-use-table.cc
src/hb-ot-shape-complex-use.cc
src/hb-ot-shape-complex-use.hh [new file with mode: 0644]
src/hb-ot-shape-complex-vowel-constraints.cc [new file with mode: 0644]
src/hb-ot-shape-complex-vowel-constraints.hh [new file with mode: 0644]
src/hb-ot-shape-complex.hh [new file with mode: 0644]
src/hb-ot-shape-fallback-private.hh [deleted file]
src/hb-ot-shape-fallback.cc
src/hb-ot-shape-fallback.hh [new file with mode: 0644]
src/hb-ot-shape-normalize-private.hh [deleted file]
src/hb-ot-shape-normalize.cc
src/hb-ot-shape-normalize.hh [new file with mode: 0644]
src/hb-ot-shape-private.hh [deleted file]
src/hb-ot-shape.cc
src/hb-ot-shape.hh [new file with mode: 0644]
src/hb-ot-stat-table.hh [new file with mode: 0644]
src/hb-ot-tag-table.hh [new file with mode: 0644]
src/hb-ot-tag.cc
src/hb-ot-tag.h [deleted file]
src/hb-ot-var-avar-table.hh
src/hb-ot-var-fvar-table.hh
src/hb-ot-var-hvar-table.hh
src/hb-ot-var-mvar-table.hh
src/hb-ot-var.cc
src/hb-ot-var.h
src/hb-ot-vorg-table.hh [new file with mode: 0644]
src/hb-ot.h
src/hb-private.hh [deleted file]
src/hb-set-digest-private.hh [deleted file]
src/hb-set-digest.hh [new file with mode: 0644]
src/hb-set-private.hh [deleted file]
src/hb-set.cc
src/hb-set.hh [new file with mode: 0644]
src/hb-shape-plan-private.hh [deleted file]
src/hb-shape-plan.cc
src/hb-shape-plan.hh [new file with mode: 0644]
src/hb-shape.cc
src/hb-shaper-impl-private.hh [deleted file]
src/hb-shaper-impl.hh [new file with mode: 0644]
src/hb-shaper-list.hh
src/hb-shaper-private.hh [deleted file]
src/hb-shaper.cc
src/hb-shaper.hh [new file with mode: 0644]
src/hb-static.cc
src/hb-string-array.hh
src/hb-subset-cff-common.cc [new file with mode: 0644]
src/hb-subset-cff-common.hh [new file with mode: 0644]
src/hb-subset-cff1.cc [new file with mode: 0644]
src/hb-subset-cff1.hh [new file with mode: 0644]
src/hb-subset-cff2.cc [new file with mode: 0644]
src/hb-subset-cff2.hh [new file with mode: 0644]
src/hb-subset-glyf.cc
src/hb-subset-glyf.hh
src/hb-subset-input.cc
src/hb-subset-input.hh [new file with mode: 0644]
src/hb-subset-plan.cc
src/hb-subset-plan.hh
src/hb-subset-private.hh [deleted file]
src/hb-subset.cc
src/hb-subset.h
src/hb-subset.hh [new file with mode: 0644]
src/hb-ucdn.cc
src/hb-ucdn/Makefile.in
src/hb-ucdn/ucdn.h
src/hb-unicode-emoji-table.hh [new file with mode: 0644]
src/hb-unicode-private.hh [deleted file]
src/hb-unicode.cc
src/hb-unicode.h
src/hb-unicode.hh [new file with mode: 0644]
src/hb-uniscribe.cc
src/hb-utf-private.hh [deleted file]
src/hb-utf.hh [new file with mode: 0644]
src/hb-vector.hh [new file with mode: 0644]
src/hb-version.h
src/hb-warning.cc
src/hb.h
src/hb.hh [new file with mode: 0644]
src/main.cc
src/test-buffer-serialize.cc
src/test-iter.cc [new file with mode: 0644]
src/test-name-table.cc [new file with mode: 0644]
src/test-ot-color.cc [new file with mode: 0644]
src/test-size-params.cc
src/test-unicode-ranges.cc
src/test-would-substitute.cc
src/test.cc
test/Makefile.in
test/api/CMakeLists.txt
test/api/Makefile.am
test/api/Makefile.in
test/api/fonts/AdobeVFPrototype.abc.otf [new file with mode: 0644]
test/api/fonts/AdobeVFPrototype.ac.nohints.otf [new file with mode: 0644]
test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf [new file with mode: 0644]
test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf [new file with mode: 0644]
test/api/fonts/AdobeVFPrototype.ac.otf [new file with mode: 0644]
test/api/fonts/AdobeVFPrototype_vsindex.otf [new file with mode: 0644]
test/api/fonts/MathTestFontFull.ttx [deleted file]
test/api/fonts/README
test/api/fonts/Roboto-Regular.multihdmx.a.ttf [new file with mode: 0644]
test/api/fonts/Roboto-Regular.multihdmx.abc.ttf [new file with mode: 0644]
test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf [new file with mode: 0644]
test/api/fonts/SourceHanSans-Regular.41,4C2E.nohints.otf [new file with mode: 0644]
test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf [new file with mode: 0644]
test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.otf [new file with mode: 0644]
test/api/fonts/SourceHanSans-Regular.41,4C2E.otf [new file with mode: 0644]
test/api/fonts/SourceSansPro-Regular.abc.otf [new file with mode: 0644]
test/api/fonts/SourceSansPro-Regular.ac.nohints.otf [new file with mode: 0644]
test/api/fonts/SourceSansPro-Regular.ac.nosubrs.nohints.otf [new file with mode: 0644]
test/api/fonts/SourceSansPro-Regular.ac.nosubrs.otf [new file with mode: 0644]
test/api/fonts/SourceSansPro-Regular.ac.otf [new file with mode: 0644]
test/api/fonts/aat-feat.ttf [new file with mode: 0644]
test/api/fonts/aat-morx.ttf [new file with mode: 0644]
test/api/fonts/aat-trak.ttf [new file with mode: 0644]
test/api/fonts/base.ttf [new file with mode: 0644]
test/api/fonts/cff1_dotsect.nohints.otf [new file with mode: 0644]
test/api/fonts/cff1_dotsect.otf [new file with mode: 0644]
test/api/fonts/cff1_expert.2D,F6E9,FB00.otf [new file with mode: 0644]
test/api/fonts/cff1_expert.otf [new file with mode: 0644]
test/api/fonts/cff1_flex.otf [new file with mode: 0644]
test/api/fonts/cff1_seac.C0.otf [new file with mode: 0644]
test/api/fonts/cff1_seac.otf [new file with mode: 0644]
test/api/fonts/chromacheck-cbdt.ttf [new file with mode: 0644]
test/api/fonts/chromacheck-colr.ttf [new file with mode: 0644]
test/api/fonts/chromacheck-sbix.ttf [new file with mode: 0644]
test/api/fonts/chromacheck-svg.ttf [new file with mode: 0644]
test/api/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5658272078495744 [new file with mode: 0644]
test/api/fonts/cpal-v0.ttf [moved from test/shaping/data/in-house/fonts/e90374e5e439e00725b4fe7a8d73db57c5a97f82.ttf with 100% similarity]
test/api/fonts/cpal-v1.ttf [moved from test/shaping/data/in-house/fonts/319f5d7ebffbefc5c5e6569f8cea73444d7a7268.ttf with 100% similarity]
test/api/fonts/cv01.otf [new file with mode: 0644]
test/api/fonts/lcar.ttf [new file with mode: 0644]
test/api/hb-subset-test.h
test/api/hb-test.h
test/api/test-aat-layout.c [new file with mode: 0644]
test/api/test-baseline.c [new file with mode: 0644]
test/api/test-blob.c
test/api/test-buffer.c
test/api/test-c.c
test/api/test-collect-unicodes.c [new file with mode: 0644]
test/api/test-common.c
test/api/test-font.c
test/api/test-map.c [new file with mode: 0644]
test/api/test-multithread.c [new file with mode: 0644]
test/api/test-object.c
test/api/test-ot-color.c
test/api/test-ot-extents-cff.c [new file with mode: 0644]
test/api/test-ot-face.c [new file with mode: 0644]
test/api/test-ot-ligature-carets.c [new file with mode: 0644]
test/api/test-ot-math.c
test/api/test-ot-name.c [new file with mode: 0644]
test/api/test-ot-tag.c
test/api/test-set.c
test/api/test-shape.c
test/api/test-subset-cff1.c [new file with mode: 0644]
test/api/test-subset-cff2.c [new file with mode: 0644]
test/api/test-subset-cmap.c
test/api/test-subset-codepoints.c [deleted file]
test/api/test-subset-glyf.c
test/api/test-subset-hdmx.c
test/api/test-subset-hmtx.c
test/api/test-subset-os2.c
test/api/test-subset-post.c
test/api/test-subset-vmtx.c
test/api/test-subset.c
test/api/test-unicode.c
test/fuzzing/CMakeLists.txt
test/fuzzing/Makefile.am
test/fuzzing/Makefile.in
test/fuzzing/fonts/0509e80afb379d16560e9e47bdd7d888bebdebc6 [moved from test/shaping/data/in-house/fonts/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf with 100% similarity]
test/fuzzing/fonts/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf [moved from test/shaping/data/in-house/fonts/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf with 100% similarity]
test/fuzzing/fonts/205edd09bd3d141cc9580f650109556cc28b22cb [moved from test/shaping/data/in-house/fonts/205edd09bd3d141cc9580f650109556cc28b22cb.ttf with 100% similarity]
test/fuzzing/fonts/217a934cfe15c548b572c203dceb2befdf026462 [moved from test/shaping/data/in-house/fonts/217a934cfe15c548b572c203dceb2befdf026462.ttf with 100% similarity]
test/fuzzing/fonts/3511ff5c1647150595846ac414c595cccac34f18 [moved from test/shaping/data/in-house/fonts/3511ff5c1647150595846ac414c595cccac34f18.ttf with 100% similarity]
test/fuzzing/fonts/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3 [moved from test/shaping/data/in-house/fonts/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf with 100% similarity]
test/fuzzing/fonts/43979b90b2dd929723cf4fe1715990bcb9c9a56b [moved from test/shaping/data/in-house/fonts/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf with 100% similarity]
test/fuzzing/fonts/558661aa659912f4d30ecd27bd09835171a8e2b0 [moved from test/shaping/data/in-house/fonts/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf with 100% similarity]
test/fuzzing/fonts/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8 [moved from test/shaping/data/in-house/fonts/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf with 100% similarity]
test/fuzzing/fonts/641bd9db850193064d17575053ae2bf8ec149ddc [moved from test/shaping/data/in-house/fonts/641bd9db850193064d17575053ae2bf8ec149ddc.ttf with 100% similarity]
test/fuzzing/fonts/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f [moved from test/shaping/data/in-house/fonts/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf with 100% similarity]
test/fuzzing/fonts/a34a9191d9376bda419836effeef7e75c1386016 [moved from test/shaping/data/in-house/fonts/a34a9191d9376bda419836effeef7e75c1386016.ttf with 100% similarity]
test/fuzzing/fonts/a69118c2c2ada48ff803d9149daa54c9ebdae30e [moved from test/shaping/data/in-house/fonts/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf with 100% similarity]
test/fuzzing/fonts/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2 [moved from test/shaping/data/in-house/fonts/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-5517117891805184 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-6107935408390144 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-4666056377368576 [moved from test/shaping/data/in-house/fonts/ef2511f215aa3ca847cbfffbf861793b42170875.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-5662671558934528 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6243458541944832 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6303297511096320 [moved from test/shaping/data/in-house/fonts/9d8a94a67932a3ab75a596fc8b5c6d0392ca9e49.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6696647723581440 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5097734906839040 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5634395566768128 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5688420752424960 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5728971283496960 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5746142327865344 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5750379279548416 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5643036478930944 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5686186874503168 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5762137968869376 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-4884742786777088 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-5255344882188288 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-5720051798769664 [moved from test/shaping/data/in-house/fonts/233c1e252e737ca79e03a9fd56b71aaa4a230f2b.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-5924299061854208 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-6460279560863744 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5126525414014976 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5166320261529600 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5659690013556736 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5662548265009152 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5973566991106048 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4523479581851648 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4535496598355968 [moved from test/shaping/data/in-house/fonts/dd9f0c7c7c36f75a18be0cab1cddf8f3ab0f366b.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4548492505645056 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4595692015190016 [moved from test/shaping/data/in-house/fonts/243798dd281c1c77c065958e1ff467420faa9bde.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4687441845813248 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4706238090706944 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4769173588672512 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4827735151083520 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4841745322868736 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4884742786777088 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5216838347653120 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5255344882188288 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5294584596791296 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5303930168803328 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5331901587914752 [moved from test/shaping/data/in-house/fonts/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5388906574905344 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5517117891805184 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5617496443846656 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5672141338968064 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5700697074958336 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5713868010553344 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5720051798769664 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5924299061854208 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6023178755244032 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6111685556305920 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6160439919509504 [moved from test/shaping/data/in-house/fonts/bbf4a308c402f0678c3e82844892a4da2ebe598f.ttf with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6210176798425088 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6260579246276608 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6264625609834496 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6278851874258944 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6424351550210048 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6460279560863744 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6576177596596224 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6595199411159040 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6624904746106880 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6723367514144768 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5175735354916864 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5629524117553152 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5630246225707008 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5631444412530688 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5633985665826816 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634443633491968 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634620935110656 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5635082459545600 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5647267827023872 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5649959857160192 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5650286710882304 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5652019562414080 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5656511058018304 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5659641787187200 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5664873493561344 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5667182741028864 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5668791174823936 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5672261407735808 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5674361600606208 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5677421274071040 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5679244475105280 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5685596677210112 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5686369209286656 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5688420752424960 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5695615258853376 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5696686572175360 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5700264032468992 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5706010589659136 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5716208469409792 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718464350650368 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718889451749376 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5719982789361664 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5722888989048832 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725129603022848 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725855502827520 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5726089628876800 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5729361857085440 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5733166795456512 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5734736291430400 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5736657639178240 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5738888765636608 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5740171484463104 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5750379279548416 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762490181353472 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762953198960640 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5764636557705216 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768046065483776 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768601332613120 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5067936541179904 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5359635656605696 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 [moved from test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 [moved from test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5629878397829120 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5651059347816448 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5660711141769216 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5669437462544384 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672006905757696 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672913680728064 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5690658895953920 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5695279609675776 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696607199166464 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5710107829075968 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5711951464759296 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5718215406125056 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5725847365877760 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5743250149736448 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5747265633779712 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5758598970343424 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5765071062958080 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5768186323009536 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6543700493598720 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 [moved from test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 with 100% similarity]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5203067375976448 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5630904853069824 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5687638085337088 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5736539338833920 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5930139383758848 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912 [new file with mode: 0644]
test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6394290358976512 [new file with mode: 0644]
test/fuzzing/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249 [moved from test/api/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249 with 100% similarity]
test/fuzzing/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54 [moved from test/api/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54 with 100% similarity]
test/fuzzing/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a [moved from test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a with 100% similarity]
test/fuzzing/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480 [moved from test/api/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480 with 100% similarity]
test/fuzzing/fonts/e88c339237f52d21e01c55f01b9c1b4cc14a0467 [moved from test/shaping/data/in-house/fonts/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf with 100% similarity]
test/fuzzing/fonts/fab39d60d758cb586db5a504f218442cd1395725 [moved from test/shaping/data/in-house/fonts/fab39d60d758cb586db5a504f218442cd1395725.ttf with 100% similarity]
test/fuzzing/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653 [moved from test/api/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653 with 100% similarity]
test/fuzzing/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a [moved from test/api/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a with 100% similarity]
test/fuzzing/hb-shape-fuzzer.cc
test/fuzzing/hb-subset-fuzzer.cc
test/fuzzing/hb-subset-get-codepoints-fuzzer.cc [deleted file]
test/fuzzing/main.cc
test/fuzzing/run-shape-fuzzer-tests.py
test/fuzzing/run-subset-fuzzer-tests.py
test/shaping/CMakeLists.txt
test/shaping/Makefile.am
test/shaping/Makefile.in
test/shaping/README.md
test/shaping/data/Makefile.am
test/shaping/data/Makefile.in
test/shaping/data/aots/COPYING [new file with mode: 0644]
test/shaping/data/aots/Makefile.am [new file with mode: 0644]
test/shaping/data/aots/Makefile.in [new file with mode: 0644]
test/shaping/data/aots/Makefile.sources [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef1_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef1_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef1_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef1_font4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef2_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef2_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef2_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/classdef2_font4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap0_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap10_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap10_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap12_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap14_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap2_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap4_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap4_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap4_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap4_font4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap6_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap6_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap8_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_composition_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_subtableselection_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_subtableselection_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_subtableselection_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_subtableselection_font4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/cmap_subtableselection_font5.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_1_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_1_simple_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_1_simple_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_2_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos1_2_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_font6.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_font7.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_next_glyph_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_2_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_2_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_2_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_2_font4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos2_2_font5.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos3_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos3_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos3_font3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos4_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos4_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos4_multiple_anchors_1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos4_simple_1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos5_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos6_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos7_1_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos9_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos9_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining1_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining2_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_chaining3_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_expansion_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context1_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_classes_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_classes_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_expansion_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context2_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gpos_context3_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub1_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub1_1_modulo_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub1_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub1_2_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub1_2_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub2_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub2_1_multiple_sequences_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub2_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub3_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub3_1_multiple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub3_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub4_1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub4_1_multiple_ligsets_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub4_1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub7_font1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub7_font2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining1_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining2_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_boundary_f3.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_boundary_f4.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_chaining3_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_expansion_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context1_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_classes_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_classes_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_expansion_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_simple_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context2_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_boundary_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_boundary_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_lookupflag_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_lookupflag_f2.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_next_glyph_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_simple_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/gsub_context3_successive_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/lookupflag_ignore_attach_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/lookupflag_ignore_base_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/lookupflag_ignore_combination_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/lookupflag_ignore_ligatures_f1.otf [new file with mode: 0644]
test/shaping/data/aots/fonts/lookupflag_ignore_marks_f1.otf [new file with mode: 0644]
test/shaping/data/aots/tests/classdef1.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef1_empty.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef1_multiple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef1_single.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef2.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef2_empty.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef2_multiple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/classdef2_single.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos1_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos1_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos1_2.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos1_2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos2_1.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos2_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos2_1_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos2_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos2_2.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos3.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos3_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos4_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos4_multiple_anchors.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos4_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos5.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos6.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos7_1.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos9.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining1_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining2_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining3_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining3_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining3_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining3_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_chaining3_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_expansion.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context1_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_classes.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_expansion.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context2_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context3_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context3_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context3_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context3_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gpos_context3_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub1_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub1_1_modulo.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub1_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub1_2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub1_2_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub2_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub2_1_multiple_sequences.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub2_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub3_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub3_1_multiple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub3_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub4_1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub4_1_multiple_ligatures.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub4_1_multiple_ligsets.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub4_1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub7.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining1_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining2_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining3_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining3_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining3_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining3_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_chaining3_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_expansion.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context1_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_classes.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_expansion.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_multiple_subrules.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context2_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context3_boundary.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context3_lookupflag.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context3_next_glyph.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context3_simple.tests [new file with mode: 0644]
test/shaping/data/aots/tests/gsub_context3_successive.tests [new file with mode: 0644]
test/shaping/data/aots/tests/lookupflag_ignore_attach.tests [new file with mode: 0644]
test/shaping/data/aots/tests/lookupflag_ignore_base.tests [new file with mode: 0644]
test/shaping/data/aots/tests/lookupflag_ignore_combination.tests [new file with mode: 0644]
test/shaping/data/aots/tests/lookupflag_ignore_ligatures.tests [new file with mode: 0644]
test/shaping/data/aots/tests/lookupflag_ignore_marks.tests [new file with mode: 0644]
test/shaping/data/in-house/Makefile.in
test/shaping/data/in-house/Makefile.sources
test/shaping/data/in-house/fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/881642af1667ae30a54e58de8be904566d00508f.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/DFONT.dfont [new file with mode: 0644]
test/shaping/data/in-house/fonts/MORXTwentyeight.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/TRAK.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/TTC.ttc [new file with mode: 0644]
test/shaping/data/in-house/fonts/ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/af85624080af5627fb050f570d148a62f04fda74.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf [deleted file]
test/shaping/data/in-house/fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf [new file with mode: 0644]
test/shaping/data/in-house/fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf [new file with mode: 0644]
test/shaping/data/in-house/tests/aat-morx.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/aat-trak.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/arabic-fallback-shaping.tests
test/shaping/data/in-house/tests/arabic-mark-attach.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/cluster.tests
test/shaping/data/in-house/tests/collections.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/color-fonts.tests
test/shaping/data/in-house/tests/cursive-positioning.tests
test/shaping/data/in-house/tests/emoji-flag-tags.tests [deleted file]
test/shaping/data/in-house/tests/emoji.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/fallback-positioning.tests
test/shaping/data/in-house/tests/fuzzed.tests [deleted file]
test/shaping/data/in-house/tests/indic-joiner-candrabindu.tests
test/shaping/data/in-house/tests/indic-joiners.tests
test/shaping/data/in-house/tests/indic-old-spec.tests
test/shaping/data/in-house/tests/indic-vowel-letter-spoofing.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/kern-format2.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/khmer-mark-order.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/khmer-misc.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/language-tags.tests
test/shaping/data/in-house/tests/macos.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/mongolian-variation-selector.tests
test/shaping/data/in-house/tests/myanmar-zawgyi.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/rand.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/spaces.tests
test/shaping/data/in-house/tests/use-indic3.tests [new file with mode: 0644]
test/shaping/data/in-house/tests/use-syllable.tests
test/shaping/data/in-house/tests/use.tests
test/shaping/data/in-house/tests/vertical.tests
test/shaping/data/text-rendering-tests/Makefile.in
test/shaping/data/text-rendering-tests/Makefile.sources
test/shaping/data/text-rendering-tests/extract-tests.py
test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXFourtyone.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyeight.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtynine.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyone.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtysix.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXThirtytwo.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXTwentyfour.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestMORXTwentynine.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/GSUB-3.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-1.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-10.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-11.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-12.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-13.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-14.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-16.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-17.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-18.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-19.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-2.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-20.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-21.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-22.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-23.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-24.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-25.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-26.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-27.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-28.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-29.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-3.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-30.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-31.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-32.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-33.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-34.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-35.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-36.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-37.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-38.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-39.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-4.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-40.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-41.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-5.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-6.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-7.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-8.tests [new file with mode: 0644]
test/shaping/data/text-rendering-tests/tests/MORX-9.tests [new file with mode: 0644]
test/shaping/hb_test_tools.py
test/shaping/record-test.sh
test/shaping/run-tests.py
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-bengali/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/misc/reph.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/misc/reph.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/dottedcircle.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/dottedcircle.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/eyelash.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/eyelash.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/joiners.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/joiners.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/spec-deviations.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/spec-deviations.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/misc/tricky-reordering.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/misc/tricky-reordering.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-kannada/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/misc/right-matras.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/misc/right-matras.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/cibu.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/cibu.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/dot-reph.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/dot-reph.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/misc/bindu.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/bindu.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/extensive.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/extensive.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/reph.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/reph.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/misc/split-matras.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/misc/split-matras.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-devanagari/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/misc/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/misc/misc.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/LICENSE [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/LICENSE with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/README [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/README with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/SOURCES [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/SOURCES with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt [moved from test/shaping/texts/in-house/shaper-indic/indic/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt with 100% similarity]
test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt [deleted file]
test/shaping/texts/in-house/shaper-khmer/misc.txt [new file with mode: 0644]
test/shaping/texts/in-house/shaper-khmer/other-marks-invalid.txt [moved from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks-invalid.txt with 100% similarity]
test/shaping/texts/in-house/shaper-khmer/other-marks.txt [moved from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/other-marks.txt with 100% similarity]
test/shaping/texts/in-house/shaper-use/script-javanese/misc.txt [moved from test/shaping/texts/in-house/shaper-indic/south-east-asian/script-javanese/misc.txt with 100% similarity]
test/subset/Makefile.am
test/subset/Makefile.in
test/subset/data/Makefile.am
test/subset/data/Makefile.in
test/subset/data/expected/full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.default.61,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.1FC,21,41,20,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.61,62,63.otf [new file with mode: 0644]
test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.D7,D8,D9,DA,DE.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,3048,304A,304B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.default.61,63,65,6B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize..otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,3048,304A,304B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.61,63,65,6B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,3048,304A,304B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.61,63,65,6B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize..otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,3048,304A,304B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.61,63,65,6B.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf [new file with mode: 0644]
test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E.otf [new file with mode: 0644]
test/subset/data/fonts/SourceHanSans-Regular.otf [new file with mode: 0755]
test/subset/data/fonts/SourceSansPro-Regular.otf [new file with mode: 0644]
test/subset/data/profiles/desubroutinize.txt [new file with mode: 0644]
test/subset/data/profiles/drop-hints-desubroutinize.txt [new file with mode: 0644]
test/subset/data/tests/full-font.tests
test/subset/data/tests/japanese.tests
test/subset/run-tests.py
test/subset/subset_test_suite.py
util/Makefile.am
util/Makefile.in
util/ansi-print.cc
util/ansi-print.hh
util/hb-shape.cc
util/hb-subset.cc
util/hb-view.cc
util/helper-cairo-ansi.hh
util/helper-cairo.cc
util/helper-cairo.hh
util/main-font-text.hh
util/options.cc
util/options.hh
util/shape-consumer.hh
util/view-cairo.hh

diff --git a/AUTHORS b/AUTHORS
index 81cdc4c..0763761 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,9 +1,11 @@
 Behdad Esfahbod
-Simon Hausmann
-Martin Hosken
+David Turner
+Ebrahim Byagowi
 Jonathan Kew
+Khaled Hosny
 Lars Knoll
-Werner Lemberg
-Roozbeh Pournader
+Martin Hosken
 Owen Taylor
-David Turner
+Roozbeh Pournader
+Simon Hausmann
+Werner Lemberg
index 8a6b569..4c1c306 100644 (file)
--- a/BUILD.md
+++ b/BUILD.md
@@ -26,7 +26,7 @@ as with any other standard package. That should leave you with a shared
 library in `src/`, and a few utility programs including `hb-view` and `hb-shape`
 under `util/`.
 
-If you are bootstraping from git, you need a few more tools before you can
+If you are bootstrapping from git, you need a few more tools before you can
 run `autogen.sh` for the first time. Namely, `pkg-config` and `ragel`.
 
 Again, on Ubuntu / Debian:
index 9ed7e56..6a1a36d 100644 (file)
@@ -52,6 +52,9 @@ if (HB_BUILD_UTILS)
   set (HB_HAVE_FREETYPE ON)
 endif ()
 
+option(HB_BUILD_SUBSET "Build harfbuzz-subset" ON)
+option(HB_BUILD_TESTS "Build harfbuzz tests" ON)
+
 option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
 if (HB_HAVE_GOBJECT)
   set (HB_HAVE_GLIB ON)
@@ -87,7 +90,6 @@ include_directories(AFTER
   ${PROJECT_BINARY_DIR}/src
 )
 
-add_definitions(-DHAVE_OT)
 add_definitions(-DHAVE_FALLBACK)
 
 # We need PYTHON_EXECUTABLE to be set for running the tests...
@@ -98,10 +100,10 @@ include (CheckFunctionExists)
 include (CheckIncludeFile)
 macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
   foreach (func_name ${ARGN})
-    string(TOUPPER ${func_name} definiton_to_add)
-    check_function_exists(${func_name} HAVE_${definiton_to_add})
-    if (${HAVE_${definiton_to_add}})
-      add_definitions(-DHAVE_${definiton_to_add})
+    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 ()
@@ -166,10 +168,6 @@ extract_make_variable(HB_BASE_headers ${SRCSOURCES})
 add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/")
 extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES})
 add_prefix_to_list(HB_FALLBACK_sources "${PROJECT_SOURCE_DIR}/src/")
-extract_make_variable(HB_OT_sources ${SRCSOURCES})
-add_prefix_to_list(HB_OT_sources "${PROJECT_SOURCE_DIR}/src/")
-extract_make_variable(HB_OT_headers ${SRCSOURCES})
-add_prefix_to_list(HB_OT_headers "${PROJECT_SOURCE_DIR}/src/")
 
 extract_make_variable(HB_SUBSET_sources ${SRCSOURCES})
 add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
@@ -178,13 +176,10 @@ 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})
-extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES})
 #if (IN_HB_DIST)
   add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
-  add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
 #else ()
 #  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
-#  add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
 #endif ()
 
 extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
@@ -210,7 +205,7 @@ set (HB_VERSION_MICRO ${CMAKE_MATCH_4})
 
 ## Define ragel tasks
 # if (NOT IN_HB_DIST)
-#  foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources} ${HB_OT_RAGEL_GENERATED_sources})
+#  foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources})
 #    string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output})
 #    set (target_name ${CMAKE_MATCH_1})
 #    add_custom_command(OUTPUT ${ragel_output}
@@ -244,8 +239,6 @@ set (project_sources
   ${HB_BASE_RAGEL_GENERATED_sources}
 
   ${HB_FALLBACK_sources}
-  ${HB_OT_sources}
-  ${HB_OT_RAGEL_GENERATED_sources}
 )
 
 set (subset_project_sources
@@ -258,7 +251,6 @@ set (project_headers
   #${HB_VERSION_H}
 
   ${HB_BASE_headers}
-  ${HB_OT_headers}
 )
 
 set (subset_project_headers
@@ -359,12 +351,32 @@ if (APPLE AND HB_HAVE_CORETEXT)
   list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc)
   list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
 
-  find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
-  if (APPLICATION_SERVICES_FRAMEWORK)
-    list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
-  endif (APPLICATION_SERVICES_FRAMEWORK)
+  if (HB_IOS)
+    find_library(COREFOUNDATION CoreFoundation)
+    if (COREFOUNDATION)
+      list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION})
+    endif ()
+    mark_as_advanced(COREFOUNDATION)
+
+    find_library(CORETEXT CoreText)
+    if (CORETEXT)
+      list(APPEND THIRD_PARTY_LIBS ${CORETEXT})
+    endif ()
+    mark_as_advanced(CORETEXT)
+
+    find_library(COREGRAPHICS CoreGraphics)
+    if (COREGRAPHICS)
+      list(APPEND THIRD_PARTY_LIBS ${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})
+    endif ()
 
-  mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
+    mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
+  endif ()
 endif ()
 
 if (WIN32 AND HB_HAVE_UNISCRIBE)
@@ -527,18 +539,20 @@ add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_heade
 target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
 
 ## Define harfbuzz-subset library
-add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
-add_dependencies(harfbuzz-subset harfbuzz)
-target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
+if (HB_BUILD_SUBSET)
+  add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
+  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)
+  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)
+  CHECK_CXX_COMPILER_FLAG(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
   if (CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
     link_libraries(-Bsymbolic-functions)
   endif ()
@@ -549,13 +563,23 @@ if (UNIX OR MINGW)
     set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
     set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
     set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
-    set_target_properties(harfbuzz-subset 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
@@ -574,7 +598,7 @@ if (HB_HAVE_GOBJECT)
 endif ()
 
 if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW)
-  add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
+  add_definitions("-DHB_DLL_EXPORT")
 endif ()
 
 # On Windows, g-ir-scanner requires a DLL build in order for it to work
@@ -680,6 +704,8 @@ if (HB_HAVE_INTROSPECTION)
       -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=
@@ -761,12 +787,22 @@ endif ()
 
 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
   )
+  install(EXPORT harfbuzzConfig
+      NAMESPACE harfbuzz::
+      DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
+  )
   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}
     )
@@ -818,52 +854,53 @@ if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
 endif ()
 
 
-## src/ executables
-foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
-  set (prog_name ${prog})
-  if (${prog_name} STREQUAL "test")
-    # test can not be used as a valid executable name on cmake, lets special case it
-    set (prog_name test-test)
-  endif ()
-  add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc)
-  target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS})
-endforeach ()
-set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
-
-## Tests
-if (UNIX OR MINGW)
-  if (BUILD_SHARED_LIBS)
-    # generate harfbuzz.def after build completion
-    string(REPLACE ";" " " space_separated_headers "${project_headers}")
-    add_custom_command(TARGET harfbuzz POST_BUILD
-      COMMAND ${CMAKE_COMMAND} -E env "headers=${space_separated_headers}" python ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def
-      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src)
-
-    add_test(NAME check-static-inits.sh
-      COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh
-      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack
-    )
-    add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh)
-    add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh)
+if (HB_BUILD_TESTS)
+  ## src/ executables
+  foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
+    set (prog_name ${prog})
+    if (${prog_name} STREQUAL "test")
+      # test can not be used as a valid executable name on cmake, lets special case it
+      set (prog_name test-test)
+    endif ()
+    add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc)
+    target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS})
+  endforeach ()
+  set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
+
+  ## Tests
+  if (UNIX OR MINGW)
+    if (BUILD_SHARED_LIBS)
+      # generate harfbuzz.def after build completion
+      add_custom_command(TARGET harfbuzz POST_BUILD
+        COMMAND "${PYTHON_EXECUTABLE}" ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def ${project_headers}
+        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src)
+
+      add_test(NAME check-static-inits.sh
+        COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh
+        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack
+      )
+      add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh)
+      add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh)
+
+      set_tests_properties(
+        check-static-inits.sh check-libstdc++.sh check-symbols.sh
+        PROPERTIES
+          ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src"
+          SKIP_RETURN_CODE 77)
+    endif ()
 
+    add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh)
+    add_test(NAME check-header-guards.sh COMMAND ./check-header-guards.sh)
+    add_test(NAME check-externs.sh COMMAND ./check-externs.sh)
+    add_test(NAME check-includes.sh COMMAND ./check-includes.sh)
     set_tests_properties(
-      check-static-inits.sh check-libstdc++.sh check-symbols.sh
+      check-c-linkage-decls.sh check-header-guards.sh check-externs.sh check-includes.sh
       PROPERTIES
-        ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src"
+        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src
         SKIP_RETURN_CODE 77)
   endif ()
 
-  add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh)
-  add_test(NAME check-header-guards.sh COMMAND ./check-header-guards.sh)
-  add_test(NAME check-externs.sh COMMAND ./check-externs.sh)
-  add_test(NAME check-includes.sh COMMAND ./check-includes.sh)
-  set_tests_properties(
-    check-c-linkage-decls.sh check-header-guards.sh check-externs.sh check-includes.sh
-    PROPERTIES
-      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src
-      SKIP_RETURN_CODE 77)
+  # Needs to come last so that variables defined above are passed to
+  # subdirectories.
+  add_subdirectory(test)
 endif ()
-
-# Needs to come last so that variables defined above are passed to
-# subdirectories.
-add_subdirectory(test)
index 7331471..135b034 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+commit fe532923101586e316b300d419a337d357cd93da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 20:47:58 2019 -0500
+
+    [CI] Peg CircleCI badge link to master branch
+
+    [skip ci]
+
+ README.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9569819e24f72926a5b26e4c8a86d815c0132745
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 20:43:43 2019 -0500
+
+    [ci] Peg build status badges to master branch
+
+    [skip ci]
+
+ README.md | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 1e29906a77c275c34a440a416654a514810485e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 20:38:15 2019 -0500
+
+    Switch README / README.md
+
+    [skip ci]
+
+ README    | 19 +------------------
+ README.md | 19 ++++++++++++++++++-
+ 2 files changed, 19 insertions(+), 19 deletions(-)
+
+commit 9a1df82e3f13fbd4488ee9955814bbb5d0957074
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 14:15:18 2019 -0500
+
+    [uniscribe] Whitelist function type cast
+
+ src/hb-uniscribe.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 6e1c3eaf7005d06c89f0807f693aadd835aa0468
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 14:12:41 2019 -0500
+
+    Fix sign comparison error
+
+ src/hb-open-file.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 9db7a7da6339eacbb6c699fa1939bbd7e9e148f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 14:09:59 2019 -0500
+
+    Fix warning
+
+    c:\projects\harfbuzz\src\hb-ot-color-cbdt-table.hh(59): warning C4146:
+    unary minus operator applied to unsigned type, result still unsigned
+    [C:\projects\harfbuzz\build\harfbuzz.vcxproj]
+
+ src/hb-ot-color-cbdt-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 51b584880e550545ced3aa8ba4ccad3cf79bb53e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 28 14:09:45 2019 -0500
+
+    [pragma] Silence MSVC unknown-pragma warning
+
+ src/hb.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 60022ecced202760daa7f75516bba6a4689a49de
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jan 26 14:04:51 2019 +0100
+
+    Fix -Wcast-function-type warnings in util/ with gcc 4.8
+
+ src/hb.hh       | 1 +
+ util/options.hh | 5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit a9321cb5f88cae1dafbd623b8bf7c68a82a3c211
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 25 16:11:45 2019 +0100
+
+    Fix mac test
+
+ test/shaping/data/in-house/tests/macos.tests | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f39809752909f193a9c60f4357a88ea1c3ce1162
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 25 16:08:25 2019 +0100
+
+    More static constexpr
+
+ src/hb-machinery.hh  | 10 +++++-----
+ src/hb-set-digest.hh | 14 +++++++-------
+ 2 files changed, 12 insertions(+), 12 deletions(-)
+
+commit 06358ae9746ae72c0917e8a5f294d14fd695f380
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 25 15:11:47 2019 +0100
+
+    [AAT] Add test for recent Ligature stack fix, using Zapfino on Mac
+
+ test/shaping/data/in-house/tests/macos.tests | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit e970de48bcbdccd29350f331288c0a98f7846c16
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 18:16:17 2019 +0100
+
+    [AAT] Minor sign
+
+ src/hb-aat-layout-morx-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a371a28cda23805cbea22867e0a3ed53ecb811ed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 18:12:25 2019 +0100
+
+    [AAT] Use a ring buffer for ligature stack
+
+    I think Apple does very similarly, but probably with a stack size
+    of 16.
+    We do it with a stack size that is currently set to 64.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1531
+
+ src/hb-aat-layout-morx-table.hh | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+commit 7886b1578fceee368ae5afe206ff98f50e1c42e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 18:06:17 2019 +0100
+
+    Whitespace
+
+ src/hb-aat-layout-morx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b976940243bf1f174bd6abb85955789ef2631d24
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 18:01:07 2019 +0100
+
+    [AAT] Handle transition errors during machine operation
+
+    Before we used to give up.  Now, just ignore error and continue
+    processing.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1531
+
+ src/hb-aat-layout-common.hh     |  3 +--
+ src/hb-aat-layout-kerx-table.hh | 21 +++++++--------------
+ src/hb-aat-layout-morx-table.hh | 34 +++++++++++++---------------------
+ 3 files changed, 21 insertions(+), 37 deletions(-)
+
+commit e234bb6a428cd6c8ddf57eb078cd51b9d1f25ba8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 17:23:11 2019 +0100
+
+    [AAT] Ignore machine errors and continue
+
+ src/hb-aat-layout-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1ec90514f69efc329691186466f62373efa863b1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 17:21:41 2019 +0100
+
+    [AAT] Minor
+
+ src/hb-aat-layout-common.hh     | 12 ++++----
+ src/hb-aat-layout-kerx-table.hh | 38 +++++++++++------------
+ src/hb-aat-layout-morx-table.hh | 68
+ ++++++++++++++++++++---------------------
+ 3 files changed, 59 insertions(+), 59 deletions(-)
+
+commit 299eca0c3b28c99add006420bc667431d874fb2e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 17:17:00 2019 +0100
+
+    [AAT] Handle out-of-bounds classes
+
+ src/hb-aat-layout-common.hh | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+commit c4623db4a3f963394db940449007fa3312460993
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 17:10:12 2019 +0100
+
+    [AAT] Minor
+
+ src/hb-aat-layout-common.hh | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+commit c4e36f97b6df1eb5fba588b09ae1630bb5c49589
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 17:06:16 2019 +0100
+
+    [AAT] Minor
+
+ src/hb-aat-layout-common.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit f60282c5bff4a317ba3180e3519274963c6e8849
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 16:29:09 2019 +0100
+
+    More pragma control
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=924848
+
+ src/hb.hh | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+commit fd0889f903ac1ba2da06e77eed8424395ea85a90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 16:12:52 2019 +0100
+
+    Comment
+
+ src/hb-ot-shape.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 00f06d1aa61e9a6d01b5943ce55ba2b0c40237ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 16:11:05 2019 +0100
+
+    Fix test
+
+ test/shaping/data/in-house/tests/cluster.tests | 1 -
+ test/shaping/data/in-house/tests/emoji.tests   | 3 ++-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 9f314177336f9551756944e0e555614c9189c7a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 16:08:33 2019 +0100
+
+    Form cluster for Emoji sub-region tag sequences
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1556
+
+ src/hb-ot-shape.cc                                       |  13
+ +++++++++++++
+ .../fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf   | Bin 0 ->
+ 1548 bytes
+ test/shaping/data/in-house/tests/cluster.tests           |   1 +
+ 3 files changed, 14 insertions(+)
+
+commit 5034f8f2ab8f53eb0395e6f6ce2f8da69a08460d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 12:50:38 2019 +0100
+
+    Fix macos tests with previous commit
+
+ test/shaping/data/in-house/tests/macos.tests | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 3ecda71041a7239ca37ec7b888809efe8f595a19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 24 12:08:23 2019 +0100
+
+    Adjust mark offsets when zeroing from fallback mark positioning code
+
+    Adjust tests.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1532
+
+ src/hb-ot-shape-fallback.cc                        | 31
+ +++++++++++++++-------
+ src/hb-ot-shape-fallback.hh                        |  3 ++-
+ src/hb-ot-shape.cc                                 |  3 ++-
+ .../in-house/tests/arabic-fallback-shaping.tests   |  2 +-
+ test/shaping/data/in-house/tests/cluster.tests     |  2 +-
+ .../data/in-house/tests/fallback-positioning.tests |  4 +--
+ 6 files changed, 30 insertions(+), 15 deletions(-)
+
+commit 36fb2b4da9718a86978fa07c99ba4345f7ca9b4b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jan 23 20:53:57 2019 +0100
+
+    [AAT] In InsertionChain, set mark to previous-position if inserting
+
+    Fixes MORX-31
+
+ src/hb-aat-layout-morx-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit cbe0ed117ac86179183c389977d15981d26524f7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jan 23 20:45:18 2019 +0100
+
+    [AAT] Re-enable tests MORX-31 and MORX-41
+
+ test/shaping/data/text-rendering-tests/DISABLED         | 3 ---
+ test/shaping/data/text-rendering-tests/Makefile.sources | 2 ++
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+commit baf4d6a68a031bf65e17ccd5dac15fe7d0df33b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jan 23 20:36:07 2019 +0100
+
+    [AAT] Remove mark_set from InsertionChain
+
+ src/hb-aat-layout-morx-table.hh | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit 410731d3fb678365c07a4d1745b72b6bb3142b70
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jan 23 20:30:48 2019 +0100
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/extract-tests.py    | 2 +-
+ test/shaping/data/text-rendering-tests/tests/MORX-14.tests | 2 +-
+ test/shaping/data/text-rendering-tests/tests/MORX-32.tests | 8 ++++----
+ test/shaping/data/text-rendering-tests/tests/MORX-41.tests | 4 ++--
+ 4 files changed, 8 insertions(+), 8 deletions(-)
+
+commit 0b2fa342de88bbe609b2147444e56c94680cbd38
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 16:36:00 2019 +0100
+
+    More of previous
+
+ src/hb-subset-cff1.cc | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+commit a5e5dd8b42b40c3647e06e6bb62580af77bed42b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 16:30:07 2019 +0100
+
+    Fix sign-compare error resulted from promoting unsigned integers to
+    signed larger ints
+
+    Clang and gcc know not to warn in these cases, but not nonmainstream
+    compilers
+
+ src/hb-subset-cff2.cc | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 32379bbf10726bb7ed2e507d0a6b5917c350e056
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:55:29 2019 +0100
+
+    Cast HB_UNTAG results to uint8_t
+
+ src/hb-common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 83d4aa5ca9a39dbe66db9b81b34f5b568503bd7e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:52:23 2019 +0100
+
+    More -Wcast-error fix
+
+ src/hb-dsalgs.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 447323b85a7b68bd41561a87c91431cd05227b97
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:45:40 2019 +0100
+
+    Better fix for -Wcast-align errors
+
+ src/hb-font.cc          | 33 +++++++++------------------------
+ src/hb-ft.cc            | 14 ++++----------
+ src/hb-machinery.hh     | 16 ++++++++++++++++
+ src/hb-ot-cmap-table.hh |  7 ++-----
+ src/hb-ot-font.cc       | 14 ++++----------
+ 5 files changed, 35 insertions(+), 49 deletions(-)
+
+commit 81ec543d800c4a94b5e608fd87e84d33d7dae8ac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:43:12 2019 +0100
+
+    More -Wcast-error fixes
+
+ src/hb-font.cc    | 8 ++++----
+ src/hb-ft.cc      | 2 +-
+ src/hb-ot-font.cc | 4 ++--
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 90772725493108c79487a67620f0240e5d68f4ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:40:18 2019 +0100
+
+    pragma GCC diagnostic error   "-Wsign-compare"
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 8d05bf7dc0094e75be07ca1f7ef852a1e45d0687
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:34:05 2019 +0100
+
+    Fix cast-align error
+
+    If compiler doesn't inline StructAtOffset, this was an error since we
+    only disable cast-align at call-site.  So, move the cast out.
+
+    ../src/hb-machinery.hh: In instantiation of 'const Type&
+    StructAtOffset(const void*, unsigned int) [with Type = unsigned int]':
+    ../src/hb-font.cc:146:85:   required from here
+    ../src/hb-machinery.hh:63:12: error: cast from 'const char*' to
+    'const unsigned int*' increases required alignment of target type
+    [-Werror=cast-align]
+     { return * reinterpret_cast<const Type*> ((const char *) P +
+     offset); }
+                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ../src/hb-machinery.hh: In instantiation of 'Type&
+    StructAtOffset(void*, unsigned int) [with Type = unsigned int]':
+    ../src/hb-font.cc:147:79:   required from here
+    ../src/hb-machinery.hh:66:12: error: cast from 'char*' to 'unsigned
+    int*' increases required alignment of target type [-Werror=cast-align]
+     { return * reinterpret_cast<Type*> ((char *) P + offset); }
+                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ src/hb-font.cc          | 8 ++++----
+ src/hb-ft.cc            | 6 +++---
+ src/hb-ot-cmap-table.hh | 4 ++--
+ src/hb-ot-font.cc       | 4 ++--
+ 4 files changed, 11 insertions(+), 11 deletions(-)
+
+commit b270cee6c5800c019aafb55e9ca9d7e92a92d3ec
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:29:05 2019 +0100
+
+    [CI] Remove gcc 4.2 bots
+
+    We don't support that version anymore.
+
+ .circleci/config.yml | 25 -------------------------
+ 1 file changed, 25 deletions(-)
+
+commit 70a52d6bd8c45630ca90e945fc4d716fe9114010
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:15:23 2019 +0100
+
+    Convert all other enum class consts to static constexpr
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1553
+
+ src/hb-cff-interp-common.hh |  2 +-
+ src/hb-iter.hh              |  2 +-
+ src/hb-machinery.hh         | 12 ++++++------
+ src/hb-open-type.hh         |  8 ++++----
+ src/hb-set-digest.hh        |  4 ++--
+ src/hb-set.hh               | 10 +++++-----
+ src/hb-vector.hh            |  2 +-
+ 7 files changed, 20 insertions(+), 20 deletions(-)
+
+commit 5d4b0377b99ddc4112b8ffb2b787eac0b383081c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:11:24 2019 +0100
+
+    Convert unsigned enum class consts to static constexpr
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1553
+
+ src/hb-aat-layout-common.hh     | 6 +++---
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-buffer.hh                | 2 +-
+ src/hb-open-type.hh             | 2 +-
+ src/hb-ot-kern-table.hh         | 4 ++--
+ src/hb-ot-layout-common.hh      | 2 +-
+ src/hb-ot-layout.cc             | 4 ++--
+ 7 files changed, 11 insertions(+), 11 deletions(-)
+
+commit ef00654962204ae706b276871e2b6758fbbf69e0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:08:57 2019 +0100
+
+    Convert tag enum class consts to static constexpr
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1553
+
+ src/hb-aat-fdsc-table.hh        |  2 +-
+ src/hb-aat-layout-ankr-table.hh |  2 +-
+ src/hb-aat-layout-bsln-table.hh |  2 +-
+ src/hb-aat-layout-feat-table.hh |  2 +-
+ src/hb-aat-layout-just-table.hh |  2 +-
+ src/hb-aat-layout-kerx-table.hh |  2 +-
+ src/hb-aat-layout-lcar-table.hh |  2 +-
+ src/hb-aat-layout-morx-table.hh |  6 +++---
+ src/hb-aat-layout-trak-table.hh |  2 +-
+ src/hb-aat-ltag-table.hh        |  2 +-
+ src/hb-ot-cff1-table.hh         |  2 +-
+ src/hb-ot-cff2-table.hh         |  2 +-
+ src/hb-ot-cmap-table.hh         |  2 +-
+ src/hb-ot-color-cbdt-table.hh   |  4 ++--
+ src/hb-ot-color-colr-table.hh   |  2 +-
+ src/hb-ot-color-cpal-table.hh   |  2 +-
+ src/hb-ot-color-sbix-table.hh   |  2 +-
+ src/hb-ot-color-svg-table.hh    |  2 +-
+ src/hb-ot-gasp-table.hh         |  2 +-
+ src/hb-ot-glyf-table.hh         |  4 ++--
+ src/hb-ot-hdmx-table.hh         |  2 +-
+ src/hb-ot-head-table.hh         |  2 +-
+ src/hb-ot-hhea-table.hh         |  4 ++--
+ src/hb-ot-hmtx-table.hh         | 12 ++++++------
+ src/hb-ot-kern-table.hh         |  6 +++---
+ src/hb-ot-layout-base-table.hh  |  2 +-
+ src/hb-ot-layout-gdef-table.hh  |  2 +-
+ src/hb-ot-layout-gpos-table.hh  |  2 +-
+ src/hb-ot-layout-gsub-table.hh  |  2 +-
+ src/hb-ot-layout-jstf-table.hh  |  2 +-
+ src/hb-ot-math-table.hh         |  2 +-
+ src/hb-ot-maxp-table.hh         |  2 +-
+ src/hb-ot-name-table.hh         |  2 +-
+ src/hb-ot-os2-table.hh          |  2 +-
+ src/hb-ot-post-table.hh         |  2 +-
+ src/hb-ot-stat-table.hh         |  2 +-
+ src/hb-ot-var-avar-table.hh     |  2 +-
+ src/hb-ot-var-fvar-table.hh     |  2 +-
+ src/hb-ot-var-hvar-table.hh     |  8 ++++----
+ src/hb-ot-var-mvar-table.hh     |  2 +-
+ src/hb-ot-vorg-table.hh         |  2 +-
+ 41 files changed, 56 insertions(+), 56 deletions(-)
+
+commit 39e1b6d03f71ccb8f18d64dfbff64acfaf02970b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:07:43 2019 +0100
+
+    Convert boolean enum class consts to static constexpr
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1553
+
+ src/hb-aat-layout-common.hh     |  4 ++--
+ src/hb-aat-layout-kerx-table.hh |  4 ++--
+ src/hb-aat-layout-morx-table.hh |  8 ++++----
+ src/hb-dsalgs.hh                | 16 ++++++++--------
+ src/hb-ot-kern-table.hh         |  4 ++--
+ src/hb-ot-layout.cc             |  4 ++--
+ 6 files changed, 20 insertions(+), 20 deletions(-)
+
+commit 271cb7c1c0f49c7af786daa5d5310b9f08142148
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:05:35 2019 +0100
+
+    Make some enum constants unsigned
+
+ src/hb-aat-layout-common.hh | 6 +++---
+ src/hb-buffer.hh            | 2 +-
+ src/hb-ot-layout.cc         | 8 ++++----
+ 3 files changed, 8 insertions(+), 8 deletions(-)
+
+commit 3d9a6e62662fb769e0f785fa7a43df806988d2a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:02:06 2019 +0100
+
+    Whitespace
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c81f02fd06fcbc4426c9e3255833f8d7057cc97a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 22 12:00:44 2019 +0100
+
+    pragma GCC diagnostic error   "-Wvla"
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ff98109455bfbf92f7633262bc570b05d15d5d01
+Author: Alfie John <alfie@alfie.wtf>
+Date:   Tue Jan 22 19:58:36 2019 +1100
+
+    Fix grammar
+
+ docs/usermanual-clusters.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e9c0f5e714cc62bcf6349b86b13e1c031f9bb764
+Author: Alfie John <alfie@alfie.wtf>
+Date:   Tue Jan 22 00:03:02 2019 +0000
+
+    Grammar fix
+
+ docs/usermanual-clusters.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 789396ed6bf2c76c1bb955e80efb43f75e3c61d2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jan 20 20:09:10 2019 -0500
+
+    Remove wrongly added files
+
+ test/api/test-ot-extents-cff                        | Bin 8574336 ->
+ 0 bytes
+ .../test-ot-extents-cff.dSYM/Contents/Info.plist    |  20
+ --------------------
+ .../Contents/Resources/DWARF/test-ot-extents-cff    | Bin 7650053 ->
+ 0 bytes
+ 3 files changed, 20 deletions(-)
+
+commit 380c3cffb9353083913a3bb505c2c62367613096
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jan 20 19:51:08 2019 -0500
+
+    Use enum for class constant
+
+ src/hb-cff-interp-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6d042a18e7079e07a2b2f465a6a56483a42ef189
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jan 20 19:49:59 2019 -0500
+
+    [CFF] Use enum for tableTag
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ src/hb-ot-cff2-table.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit c1cbbb94595641f0609cc8d2dbe8415540c10f77
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jan 20 19:47:52 2019 -0500
+
+    Use static constexpr for large class constants
+
+ src/hb-map.hh | 2 +-
+ src/hb-set.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 30ae62779f1a68c5657ab27bc7e77496ba8a906c
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Mon Jan 21 16:44:48 2019 +0200
+
+    Regular spaces will do
+
+ docs/usermanual-getting-started.xml | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit ed62551d67ac5bb8dbfaf3fa5eb51013157b214a
+Author: Alfie John <alfie@alfie.wtf>
+Date:   Mon Jan 21 05:00:01 2019 +0000
+
+    Adding leading space for code example
+
+ docs/usermanual-getting-started.xml | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 3e332544db35ca08de767ecab01b489a9905c559
+Author: Alfie John <alfie@alfie.wtf>
+Date:   Mon Jan 21 04:54:27 2019 +0000
+
+    Fix description of example
+
+ docs/usermanual-getting-started.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2144ca9f01d01b6de386d17ada73a288372ee553
+Author: Alfie John <alfie@alfie.wtf>
+Date:   Mon Jan 21 04:47:05 2019 +0000
+
+    Added option to build docs to docs
+
+ docs/usermanual-install-harfbuzz.xml | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+commit 043b610fa698ed247347dfaa042f032f3fd3f572
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jan 19 09:20:46 2019 -0500
+
+    Fix sign compare warnings
+
+    ../../third_party/harfbuzz-ng/src/src/hb-map.hh(56,45):  warning:
+    comparison of integers of different signs: 'const hb_codepoint_t'
+    (aka 'const unsigned int') and 'hb_map_t::(anonymous enum
+    at ../../third_party/harfbuzz-ng/src/src/hb-map.hh:169:3)'
+    [-Wsign-compare]
+        bool is_unused () const    { return key == INVALID; }
+
+ src/hb-map.hh | 2 +-
+ src/hb-set.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit ce317d032061d81c520180a338172ce38b427135
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jan 19 09:18:03 2019 -0500
+
+    Fix warning
+
+    warning: '_WIN64' is not defined, evaluates to 0 [-Wundef]
+
+ src/hb-dsalgs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0c2bd1b160fda4e77919889ac80f9460967fa251
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Jan 19 16:30:07 2019 +0330
+
+    [dwrite] Fix delete-non-virtual-dtor warning (#1550)
+
+ src/hb-directwrite.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 89bcfb204c736f5962d377896af2c1350f179882
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 14:59:18 2019 -0500
+
+    Remove TRACE_COLLECT_GLYPHS
+
+ src/hb-debug.hh                | 13 -------------
+ src/hb-ot-layout-gpos-table.hh | 26 ++++----------------------
+ src/hb-ot-layout-gsub-table.hh | 21 +++------------------
+ src/hb-ot-layout-gsubgpos.hh   | 12 +-----------
+ 4 files changed, 8 insertions(+), 64 deletions(-)
+
+commit f13b6786f0aefd2060ca976f7e42db7387b49450
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 14:53:54 2019 -0500
+
+    [pragma] Only add if GCC or clang
+
+ src/hb.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit c2ea7a9da463c567d321233b23813c59762841bb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 13:45:33 2019 -0500
+
+    [directwrite] More fix
+
+ src/hb-directwrite.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9714d3ec5c45b2fe460fa6b21bdb3487c62029d3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Jan 18 21:55:21 2019 +0330
+
+    [dwrite] Try to fix delete-non-virtual-dtor warnings
+
+    Fixes #1548 hopefully
+
+ src/hb-directwrite.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0772c06f96c3f5a319485c390416531b8125251b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 12:53:06 2019 -0500
+
+    Remove tracing from closure
+
+ src/hb-debug.hh                | 13 -------------
+ src/hb-ot-layout-gsub-table.hh | 15 ++-------------
+ src/hb-ot-layout-gsubgpos.hh   | 14 +-------------
+ 3 files changed, 3 insertions(+), 39 deletions(-)
+
+commit d9f6be3a61edfe9e1bce01ea9b11e2bcb16f9618
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 12:48:01 2019 -0500
+
+    Fix -Wundef errors with __GNUC__
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1549
+
+ src/hb-common.h |  4 ++--
+ src/hb.hh       | 10 +++++-----
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 28917e58f973e5875d3ef3004c16e1ee1a5a973c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Jan 18 09:43:51 2019 -0800
+
+    init interp_env_t::hintmask_size
+
+    fixes issue #1547
+
+ src/hb-cff-interp-cs-common.hh                      |   1 +
+ test/api/test-ot-extents-cff                        | Bin 0 ->
+ 8574336 bytes
+ .../test-ot-extents-cff.dSYM/Contents/Info.plist    |  20
+ ++++++++++++++++++++
+ .../Contents/Resources/DWARF/test-ot-extents-cff    | Bin 0 ->
+ 7650053 bytes
+ 4 files changed, 21 insertions(+)
+
+commit 9b4e51b2e44d7dea026b1f9201d2f83277bab1cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 12:23:02 2019 -0500
+
+    [pragma] Enable error -Wdelete-non-virtual-dtor
+
+    Currently fails directwrite backend.
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit e65272281c71d416f0ff886a55536597665b9dc3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 12:22:07 2019 -0500
+
+    [directwrite] Fix error
+
+    hb-directwrite.cc: In constructor 'TextAnalysis::TextAnalysis(const
+    wchar_t*, uint32_t, const wchar_t*, DWRITE_READING_DIRECTION)':
+    hb-directwrite.cc:489:18: error: 'TextAnalysis::mText' will be
+    initialized after [-Werror=reorder]
+       const wchar_t* mText;
+                      ^~~~~
+    hb-directwrite.cc:488:12: error:   'uint32_t
+    TextAnalysis::mTextLength' [-Werror=reorder]
+       uint32_t mTextLength;
+                ^~~~~~~~~~~
+    hb-directwrite.cc:282:3: error:   when initialized here
+    [-Werror=reorder]
+       TextAnalysis (const wchar_t* text, uint32_t textLength,
+       ^~~~~~~~~~~~
+    hb-directwrite.cc: In function 'hb_bool_t
+    _hb_directwrite_shape_full(hb_shape_plan_t*, hb_font_t*, hb_buffer_t*,
+    const hb_feature_t*, unsigned int, float)':
+
+ src/hb-directwrite.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b900f78088abb87ebec263474b2802593afa0264
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 10:08:23 2019 -0500
+
+    [pragma] More cast-align whitelist
+
+ src/hb-font.cc          | 20 +++++++++++++++-----
+ src/hb-ft.cc            |  6 ++++++
+ src/hb-ot-cmap-table.hh |  3 +++
+ src/hb-ot-font.cc       |  6 ++++++
+ 4 files changed, 30 insertions(+), 5 deletions(-)
+
+commit 0d8b931bbeee9743d2e3bd37dd2fa9dffb807eaa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 10:03:43 2019 -0500
+
+    [pragma] Allow cast-align in hb-font.cc
+
+    ../src/hb-machinery.hh: In instantiation of 'const Type&
+    StructAtOffset(const void*, unsigned int) [with Type = unsigned int]':
+    ../src/hb-font.cc:144:85:   required from here
+    ../src/hb-machinery.hh:63:12: error: cast from 'const char*' to
+    'const unsigned int*' increases required alignment of target type
+    [-Werror=cast-align]
+     { return * reinterpret_cast<const Type*> ((const char *) P +
+     offset); }
+                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ../src/hb-machinery.hh: In instantiation of 'Type&
+    StructAtOffset(void*, unsigned int) [with Type = unsigned int]':
+    ../src/hb-font.cc:145:79:   required from here
+    ../src/hb-machinery.hh:66:12: error: cast from 'char*' to 'unsigned
+    int*' increases required alignment of target type [-Werror=cast-align]
+     { return * reinterpret_cast<Type*> ((char *) P + offset); }
+                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ../src/hb-machinery.hh: In instantiation of 'Type&
+    StructAtOffset(void*, unsigned int) [with Type = int]':
+
+ src/hb-font.cc | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit a25174a56b8fc334a050aa63be3654f53a7d8893
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 09:59:36 2019 -0500
+
+    [pragma] GCC diagnostic error   "-Wreorder"
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 4660090569efbf64d3acc99ef6fa33e01abc9701
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 09:53:16 2019 -0500
+
+    [pragma] GCC diagnostic warning "-Wmaybe-uninitialized"
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 7a634d7d5b859eb1121acd0b17c727c541a7f540
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 09:49:14 2019 -0500
+
+    [pragma] Massage more
+
+ src/hb.hh | 106
+ ++++++++++++++++++++++++++++++++------------------------------
+ 1 file changed, 55 insertions(+), 51 deletions(-)
+
+commit 16e5ba85b1822ff9d2b2f85f45ddd44f1a05f4b1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 09:46:17 2019 -0500
+
+    [pragma] More
+
+ src/hb.hh | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+commit 2bd530d59883cce437a5093323625f94b9618d89
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 09:28:22 2019 -0500
+
+    [pragma] Reorg again
+
+    https://github.com/harfbuzz/harfbuzz/issues/1546
+
+ src/hb.hh | 91
+ ++++++++++++++++++++++++++++++++-------------------------------
+ 1 file changed, 46 insertions(+), 45 deletions(-)
+
+commit c04272fac81cac48b6310182d58d54569117f298
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jan 18 08:49:45 2019 -0500
+
+    [pragma] GCC diagnostic ignored "-Wunknown-warning-option"
+
+    Try at fixing https://github.com/harfbuzz/harfbuzz/issues/1546
+
+ src/hb.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 4d3c8f9685b1744077ab264ffc0e0457d63c4b9a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:58:54 2019 -0500
+
+    [uniscribe] More warnings
+
+ src/hb-uniscribe.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 6a5d2b21d8457001a59537e85596461feba3dbd5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:57:17 2019 -0500
+
+    [uniscribe] Fix warnings
+
+ src/hb-uniscribe.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 5b13e458c34d16fef6540a9389225e0597a99df5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:52:32 2019 -0500
+
+    Fix build
+
+ src/hb-directwrite.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit a77bd6bb8960ecff35aac07f221653c65d08e58e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:33:41 2019 -0500
+
+    [pragma] GCC diagnostic ignored "-Wclass-memaccess"
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e1302842d9c589ccbed90d29c953fea503d3901f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:12:07 2019 -0500
+
+    [ci] Remove unnecessary warning declarations
+
+    clang -Weverything still left to be ported to pragmas
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 436c7b294ab12ae338aaa879fe4280caae6c6155
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:03:33 2019 -0500
+
+    [pragma] ignored -Wunsafe-loop-optimizations // TODO fix
+
+ src/hb.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e3b3181e9ddd8b76428d7eaca64a3e03a99fcdd5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 19:02:06 2019 -0500
+
+    [pragma] error -Wclass-memaccess
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 1a6b97a491f2ba4f84e52c89517b7a02faa70cc3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:55:03 2019 -0500
+
+    [pragma] More
+
+ src/hb.hh | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+commit 06e8091661352873c4d6040fd06a940136497e6f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:47:32 2019 -0500
+
+    [pragma] More
+
+ src/hb.hh | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+commit 1077e40bf12f998976df4bf509c69df9f9e2a590
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:36:10 2019 -0500
+
+    [pragma] Flesh out more
+
+ src/hb.hh | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+commit 7e6bd510fc695c423a7fa6b25c15805482f7d185
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:24:18 2019 -0500
+
+    Use NNOffsetTo<> in rest of places
+
+ src/hb-aat-layout-common.hh     |  8 ++++----
+ src/hb-aat-layout-kerx-table.hh | 22 +++++++++++-----------
+ src/hb-aat-layout-morx-table.hh | 10 +++++-----
+ 3 files changed, 20 insertions(+), 20 deletions(-)
+
+commit b1152d5e66d7463a30af8ca2a485f75e0c8e6ffd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:17:04 2019 -0500
+
+    Use NNOffsetTo<>
+
+ src/hb-aat-layout-ankr-table.hh |  6 +++---
+ src/hb-aat-layout-trak-table.hh |  2 +-
+ src/hb-aat-ltag-table.hh        |  2 +-
+ src/hb-open-file.hh             | 10 +++++-----
+ src/hb-ot-cff2-table.hh         |  6 +++---
+ src/hb-ot-color-cbdt-table.hh   |  2 +-
+ src/hb-ot-color-colr-table.hh   |  4 ++--
+ src/hb-ot-color-cpal-table.hh   |  8 ++++----
+ src/hb-ot-color-svg-table.hh    |  2 +-
+ src/hb-ot-name-table.hh         |  2 +-
+ src/hb-ot-stat-table.hh         |  4 ++--
+ 11 files changed, 24 insertions(+), 24 deletions(-)
+
+commit 205d72a198805ba276c1d0e63b1ca313c7bd517f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 18:10:38 2019 -0500
+
+    Add NNOffsetTo<>
+
+ src/hb-open-type.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit c99d13d860e3d34e16cd2c070070d4f5d7d58cf4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 17:56:27 2019 -0500
+
+    [AAT] Comment
+
+ src/hb-aat-layout-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f39b5603ffa0452528b2366f8641e7e770960847
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 17:49:55 2019 -0500
+
+    Comment
+
+ src/hb-ot-layout-gpos-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 347ad454b88b89fc4bc30fca86c9ca37bea0be5b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 17:47:29 2019 -0500
+
+    [AAT] Remove unused code
+
+ src/hb-aat-layout-ankr-table.hh |  3 +--
+ src/hb-aat-layout-common.hh     |  3 +--
+ src/hb-aat-layout-kerx-table.hh |  6 ++----
+ src/hb-aat-layout.cc            | 14 +++-----------
+ 4 files changed, 7 insertions(+), 19 deletions(-)
+
+commit b344d4385af5bc9adac2a24850cb963929d4ae9e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 17:44:39 2019 -0500
+
+    [AAT] Allow null in ankr lookupTable offset
+
+ src/hb-aat-layout-ankr-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 14a560a245109376b7314c949895968d0a54452c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 17:42:44 2019 -0500
+
+    [pragma GCC] Ignore -Wtype-limits
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 41b4312e936a0dfc396e6f0ef13c2c691dac6e40
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 16:07:27 2019 -0500
+
+    [ci] Remove -Werror from Travis
+
+    hb-machinery.hh:111:37: warning: comparison of unsigned expression >=
+    0 is always true [-Wtype-limits]
+
+    Also ignore -Wtype-limits.
+
+ .travis.yml | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 3f2daae63073bd536bceb1ae71dffd3187afce11
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 15:27:31 2019 -0500
+
+    More GCC pragmas
+
+ src/hb.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit d6c5473e1f86cae7f1060abe18f73ccb8e536d6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 15:22:46 2019 -0500
+
+    Rename macro
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a9946b7cfef185d53304e804169d6e53e9d522a0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 15:22:28 2019 -0500
+
+    Add more GCC warning pragmas
+
+ src/hb.hh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+commit 868b0c0c2e2f1a2dea9b0d3c8eb6e56ded8b1a14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 15:08:36 2019 -0500
+
+    Move -Wcast-align to hb.hh
+
+ configure.ac | 3 ---
+ src/hb.hh    | 4 ++++
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+commit 8874eef8ff70de6416266d719fa74eec39e5d8f9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 15:04:44 2019 -0500
+
+    Add pragram GCC diagnostic ignored "-Wunused-macros"
+
+ src/gen-indic-table.py                 | 3 +++
+ src/gen-use-table.py                   | 3 +++
+ src/hb-blob.cc                         | 3 +++
+ src/hb-ot-shape-complex-indic-table.cc | 3 +++
+ src/hb-ot-shape-complex-use-table.cc   | 3 +++
+ 5 files changed, 15 insertions(+)
+
+commit cc8e9a436fa408a1c63f4b9afb7643cea76a079c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 14:54:32 2019 -0500
+
+    [AAT] Fully sanitize ankr table at sanitize time
+
+    Third try to fix access. Followup
+    6879efc2c1596d11a6a6ad296f80063b558d5e0f
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12532
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=922303
+
+ src/hb-aat-layout-ankr-table.hh | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+commit 6879efc2c1596d11a6a6ad296f80063b558d5e0f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 14:06:37 2019 -0500
+
+    [AAT] Fix anchor bound checking, again
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12532
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=922303
+
+ src/hb-aat-layout-ankr-table.hh                           |   3 ++-
+ ...zz-testcase-minimized-harfbuzz_fuzzer-5166320261529600 | Bin 0 ->
+ 393 bytes
+ ...zz-testcase-minimized-hb-shape-fuzzer-5667182741028864 | Bin 0 ->
+ 407 bytes
+ 3 files changed, 2 insertions(+), 1 deletion(-)
+
+commit a262eb3d0b7009aabd9e0beebc77e5c0a2a65548
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jan 17 14:06:32 2019 -0500
+
+    [aat] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit c986ca15a6320d78471adf950394f391e8729b15
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jan 15 13:58:19 2019 -0500
+
+    Improve overflow avoidance
+
+    Better fix for 480406cd3ef9e5ab8476ddfa04498bf23906c508
+    This way we behave the same on 32bit and 64bit archs.
+
+ src/hb-machinery.hh | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+commit 0d2727f4fe734af146785df10a44e3505e410ba1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 18:23:17 2019 -0800
+
+    fix FDSelect fuzzing bug (#1539)
+
+    Rewrote struct FDSelect3_4.ranges as ArrayOf
+    Updated FDSelect3_4::sanitize () to call ranges.sanitize ()
+    nRanges now a function to return a reference to ranges.len
+
+ src/hb-ot-cff-common.hh     | 29 +++++++++++++++--------------
+ src/hb-subset-cff-common.cc |  2 +-
+ 2 files changed, 16 insertions(+), 15 deletions(-)
+
+commit 9f6172d669d53abbf3bf2a3546429cb5036e3d5f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 20:45:31 2019 -0500
+
+    Move _POSIX_SOURCE definition
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1308
+
+ src/hb-blob.cc | 9 +++++++++
+ src/hb.hh      | 4 ----
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+commit 91d774712fa76dd26c441526712bddddca5b4bdd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 15:31:31 2019 -0500
+
+    [test] Add test for previous commit
+
+ ...uzz-testcase-minimized-harfbuzz_fuzzer-5662548265009152 | Bin 0 ->
+ 28 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 480406cd3ef9e5ab8476ddfa04498bf23906c508
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 15:27:34 2019 -0500
+
+    Fix assertion on address overflow
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=917031
+
+ src/hb-machinery.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 7a6686a589ed6bf17a5af0b8012501e4d4ee2ded
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 15:09:14 2019 -0500
+
+    [AAT] Fix mort ContextualSubtable offset access
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12312
+
+ src/hb-aat-layout-morx-table.hh                           |   3 ++-
+ ...zz-testcase-minimized-hb-shape-fuzzer-5631444412530688 | Bin 0 ->
+ 336 bytes
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit a3fa7d33360a58df5333dbbd121328e580f08849
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jan 14 14:37:36 2019 -0500
+
+    [AAT] Fix ankr table access
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=918340
+
+ src/hb-aat-layout-ankr-table.hh                          |   7 ++++---
+ ...z-testcase-minimized-harfbuzz_fuzzer-5126525414014976 | Bin 0 ->
+ 1141 bytes
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+commit 760303d411b1561533f8f08c7c15db331c71ece8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Jan 11 15:27:35 2019 -0800
+
+    deleted a duplicate fontdicts_mod.fini() call (#1538)
+
+ src/hb-subset-cff1.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 5110f3da9a4711a35bfb780ea06cda677cc00209
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jan 9 16:01:11 2019 +0330
+
+    Add an initial .clang-format config
+
+    There are things can be improved on clang-format side I guess before
+    the full assertion, but is the best we can get for now I guess.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1536
+
+ .clang-format | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+commit 099bca6d406af9c8e12a66b93fcc9a38ff7914f9
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jan 9 15:56:32 2019 +0330
+
+    Minor, hack .editorconfig for vscode use
+
+    As VSCode and Atom https://github.com/Microsoft/vscode/issues/44438
+    don't support it
+
+ .editorconfig | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 7b48641aa8551115d21c534940ac4fb364e5ab92
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Jan 8 12:37:48 2019 -0800
+
+    fix leak in subset_enc_supp_codes (#1537)
+
+    oss-fuzz issue 12310
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 97f67a3c3d499959d33e66aeed449e2957a14bc6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Jan 4 23:10:39 2019 +0330
+
+    [ci] Enable more of GCC compile warnings (#1533)
+
+ .circleci/config.yml      | 16 ++++++++--------
+ src/hb-gobject-structs.cc |  4 ++--
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit ad954870383a880262edcd01acd8e171c4614a68
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Mon Dec 3 12:49:44 2018 -0600
+
+    Usermanual: small formatting and wording fixes.
+
+ docs/usermanual-getting-started.xml  |  3 +++
+ docs/usermanual-install-harfbuzz.xml | 30 ++++++++++++++----------------
+ docs/usermanual-what-is-harfbuzz.xml | 11 ++++++-----
+ 3 files changed, 23 insertions(+), 21 deletions(-)
+
+commit ed13caddf2de68312608e12c37d0e6287c1ac0a0
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Wed Nov 28 13:48:38 2018 -0600
+
+    Usermanual: small updates.
+
+ ...anual-buffers-language-script-and-direction.xml |   7 +-
+ docs/usermanual-clusters.xml                       | 279
+ ++++++++++++++++-----
+ docs/usermanual-getting-started.xml                |  91 ++++++-
+ docs/usermanual-install-harfbuzz.xml               |   3 +-
+ docs/usermanual-shaping-concepts.xml               |  11 +-
+ 5 files changed, 314 insertions(+), 77 deletions(-)
+
+commit 26c5b54fb09fb45e02c9c4618bcea4958c698953
+Author: cclauss <cclauss@me.com>
+Date:   Mon Dec 31 04:30:43 2018 +0100
+
+    CircleCI: Test for Python 3 syntax errors and undefined names (#1522)
+
+    Catch missing imports and errors like #1520 and #1521
+
+    __E901,E999,F821,F822,F823__ are the "_showstopper_"
+    [flake8](http://flake8.pycqa.org) issues that can halt the runtime
+    with a SyntaxError, NameError, etc. Most other flake8 issues are
+    merely "style violations" -- useful for readability but they do not
+    effect runtime safety.
+    * F821: undefined name `name`
+    * F822: undefined name `name` in `__all__`
+    * F823: local variable name referenced before assignment
+    * E901: SyntaxError or IndentationError
+    * E999: SyntaxError -- failed to compile a file into an Abstract
+    Syntax Tree
+
+ .circleci/config.yml             | 3 ++-
+ src/gen-use-table.py             | 4 +++-
+ test/subset/subset_test_suite.py | 2 +-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+commit 686e6f2e40da378e031b4c9871a471599c6d61cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 30 11:27:42 2018 -0500
+
+    Fix automake warnings
+
+    [skip ci]
+
+ test/api/Makefile.am         | 1 -
+ test/subset/data/Makefile.am | 2 +-
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+commit b5c12b9f4d2c32a5013c340f7e40649cb5f2b41a
+Author: cclauss <cclauss@me.com>
+Date:   Sun Dec 30 13:07:28 2018 +0100
+
+    print() is a function in Python 3 (#1520)
+
+ test/subset/generate-expected-outputs.py | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit f4da28b1f153ccf293b367363a1a4d83c056e4e1
+Author: cclauss <cclauss@me.com>
+Date:   Sun Dec 30 12:58:34 2018 +0100
+
+    Python 3 fixes to gen-os2-unicode-ranges.py (#1521)
+
+    In Python 3, __reload()__ was moved and __sys.setdefaultencoding()__
+    because the default is already utf-8.  Also __Error()__ is an
+    _undefined name_ and __Exception()__ creates a generic exception.
+
+ src/gen-os2-unicode-ranges.py | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+commit e5989e0962309b27b2486d8fd20f3cbc05c3d79a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Dec 30 10:23:47 2018 +0330
+
+    [cmake] Enable C++11 on CMake (#1519)
+
+ CMakeLists.txt | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+commit d092fb27198f24423e51ce07375ebd6d486f64d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 30 01:53:03 2018 -0500
+
+    Ouch! Fix build on C++<11
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 89949ed28db96edabeb09433fcc09f28168163d2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 30 01:52:19 2018 -0500
+
+    Fix ubsan with passing nullptr to qsort()
+
+ src/hb-array.hh | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 357a0a7ad344caf898eb1697fcdb859d118b7a13
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 18:29:23 2018 -0500
+
+    Fix build on C++ < 11
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 54c0a1731069a17ae4f3b79b419af75709f03f5b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 18:27:36 2018 -0500
+
+    [vector] Fix warning
+
+ src/hb-vector.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 1043ddbee878a14df0ad8d83fbaa893370ef5a75
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 18:27:11 2018 -0500
+
+    [aat] Minor
+
+ src/hb-aat-layout-morx-table.hh | 2 +-
+ src/hb-aat-map.hh               | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 71da9ca62fa87bd3e0fa9d40924bb4c220313a03
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 18:01:06 2018 -0500
+
+    [vector] Remove use of arrayZ() by using casts
+
+ src/hb-ot-name-table.hh | 2 +-
+ src/hb-ot-name.cc       | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit fa333e34d6230210bc73a88b0ba6df2102dcda51
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 17:56:22 2018 -0500
+
+    [vector] Remove static_array
+
+    Was good idea, but with C++ types with constructor/destructor,
+    was getting in
+    the way as compiler was destructing those items where it was not
+    desired.
+    Since C++ does not allow zero-sized arrays, just remove it...
+
+ src/hb-aat-map.hh            |  4 ++--
+ src/hb-cff-interp-common.hh  |  2 +-
+ src/hb-face.cc               |  2 +-
+ src/hb-object.hh             |  2 +-
+ src/hb-ot-cff-common.hh      |  2 +-
+ src/hb-ot-layout-gsubgpos.hh |  2 +-
+ src/hb-ot-map.hh             | 10 +++++-----
+ src/hb-ot-post-table.hh      |  2 +-
+ src/hb-set.hh                |  4 ++--
+ src/hb-vector.hh             | 34 +++++++++++-----------------------
+ src/hb.hh                    |  3 +++
+ 11 files changed, 29 insertions(+), 38 deletions(-)
+
+commit ab2258a419abbace9ff27916143b46f88e8ccef3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 27 17:45:05 2018 -0500
+
+    [vector] Use allocated = -1 to signify failure
+
+ src/hb-vector.hh | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+commit 09fa536d89d969998fe6bbe274a9964c73d1d982
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Dec 27 08:33:09 2018 -0800
+
+    fix lealk with cff2::accelerator_templ_t::topDict (#1517)
+
+ src/hb-ot-cff2-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 3b81442cd5c11099ae9245074d24ef679b4473fa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 24 11:31:04 2018 -0500
+
+    [vector] Change pre-alloced count from 8 to 2
+
+    I'm thinking about dropping it to zero, but that needs slight code
+    changes.
+
+ src/hb-vector.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d25a2f1496d13846ddaea123ac6fb9807dc5669a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 23 20:19:52 2018 -0500
+
+    Fix a few warnings
+
+ src/hb-aat-layout-common.hh | 12 ++++++------
+ src/hb-iter.hh              |  8 ++++----
+ src/hb-null.hh              |  2 +-
+ src/hb-ot-cff1-table.hh     |  2 +-
+ src/hb-ot-cff2-table.hh     |  2 +-
+ src/hb-subset-cff-common.hh |  3 ++-
+ src/hb.hh                   |  3 ++-
+ 7 files changed, 17 insertions(+), 15 deletions(-)
+
+commit 85003b594b3aa1f6638e274bc89f18999a5de9f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 22 16:19:10 2018 -0500
+
+    [iter] Fix warning
+
+ src/hb-iter.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e4355b1ca177200db6769136ead1ee25da86ec85
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 22 16:11:22 2018 -0500
+
+    [set] Add iter_t as alias to const_iter_t
+
+ src/hb-set.hh    | 6 ++++--
+ src/test-iter.cc | 2 ++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+commit 33f8de61863efa538c488121c476fd0e907020d0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 22 15:10:18 2018 -0500
+
+    [set] Change to const_iter
+
+ src/hb-set.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit f88fed5cd8787e3deeec05dac4353337dc02abdd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 22 11:11:10 2018 -0500
+
+    [set] Cache length in iterator
+
+ src/hb-set.hh | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit d0a706c7fdb72a1d224b4a5bdbad0fb8c90e3186
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Dec 22 19:47:48 2018 +0330
+
+    Minor, remove redundant inline
+
+ src/hb-ot-layout.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit ae6e348d642194585543f0d548fb94d210575fe4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Dec 22 19:47:29 2018 +0330
+
+    Minor, tweak spaces
+
+ src/hb-ot-glyf-table.hh     |  8 ++++----
+ src/hb-subset-cff-common.hh | 15 ++++++---------
+ 2 files changed, 10 insertions(+), 13 deletions(-)
+
+commit 29f0b6bce7da4c599f54066f7e7f6000f10d2f29
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Dec 22 07:47:04 2018 -0800
+
+    CFF renaming (#1507)
+
+    * reimplement ByteStr as byte_str_t based on hb_ubytes_t
+
+    Unuse start_embed<ByteStr>
+    Also renamed SubByteStr to byte_str_ref_t
+    More renaming to come
+
+    * substr renamed to str_ref in line with its type byte_str_ref_t
+
+    * uncamelize non-table struct names
+
+    * uncamelized non-struct types OpCode etc
+
+    * add byte_str_t copy ctor
+
+    * test
+
+    * test2
+
+    * undo tests
+
+    * fix bot failure
+
+    * undo the previous change
+
+    * fixed tabs, added inline
+
+    * Revert "fixed tabs, added inline"
+
+    This reverts commit 21163c30e9d18759414f7fe2518628241599f039.
+
+    * fix tabs
+
+ src/hb-cff-interp-common.hh      | 215 +++++++++++++++------------------
+ src/hb-cff-interp-cs-common.hh   | 250
+ +++++++++++++++++++--------------------
+ src/hb-cff-interp-dict-common.hh |  64 +++++-----
+ src/hb-cff1-interp-cs.hh         |  26 ++--
+ src/hb-cff2-interp-cs.hh         |  56 ++++-----
+ src/hb-ot-cff-common.hh          |  59 ++++-----
+ src/hb-ot-cff1-table.cc          |  56 ++++-----
+ src/hb-ot-cff1-table.hh          | 147 ++++++++++++-----------
+ src/hb-ot-cff2-table.cc          |  28 ++---
+ src/hb-ot-cff2-table.hh          | 128 ++++++++++----------
+ src/hb-subset-cff-common.cc      |  10 +-
+ src/hb-subset-cff-common.hh      | 232
+ ++++++++++++++++++------------------
+ src/hb-subset-cff1.cc            | 244
+ +++++++++++++++++++-------------------
+ src/hb-subset-cff2.cc            | 100 ++++++++--------
+ 14 files changed, 796 insertions(+), 819 deletions(-)
+
+commit 89d04129e2f4dedb865635dcb8f0fd020e4218c2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 20:07:52 2018 -0500
+
+    [set] Actually derive iterator from hb_sorted_iter_t<>
+
+ src/hb-set.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fc35919d015c5b8d231933d6bc6ea640c83af6b2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 20:06:17 2018 -0500
+
+    [set] Implement unified iterator
+
+ src/hb-set.hh | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+commit 4911e67d2d2188ee9bdc0315e121e51d9967b567
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 20:00:52 2018 -0500
+
+    [set] Mark some internals protected
+
+ src/hb-set.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 954b985422a8964f6e7da9f71ab7a68074017111
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 19:55:02 2018 -0500
+
+    [iter] Add hb_sorted_iter_t<>
+
+ src/hb-array.hh |  2 +-
+ src/hb-iter.hh  | 11 +++++++++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+commit b205105c9e1c6295b17cfd88ffb8ca7d963ef173
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 19:48:21 2018 -0500
+
+    [iter] Change operator[] operand to be signed
+
+    To fix older compilers again (this was the case in hb_array_t).
+
+    hb-ot-layout-common.hh:1353: note: candidate 2: operator[](T*,
+    int) <built-in>
+    hb-ot-layout-common.hh:1354: error: ISO C++ says that these are
+    ambiguous, even though the worst conversion for the first is better
+    than the worst conversion for the second:
+    hb-iter.hh:63: note: candidate 1: Item& hb_iter_t<Iter,
+    Item>::operator[](unsigned int) const [with Iter = hb_array_t<const
+    OT::IntType<short unsigned int, 2u> >, Item = const OT::IntType<short
+    unsigned int, 2u>]
+    hb-ot-layout-common.hh:1354: note: candidate 2: operator[](T*,
+    int) <built-in>
+    hb-ot-layout-common.hh: In member function 'bool
+    OT::ClassDef::serialize(hb_serialize_context_t*, hb_array_t<const
+    OT::IntType<short unsigned int, 2u> >, hb_array_t<const
+    OT::IntType<short unsigned int, 2u> >)':
+    hb-ot-layout-common.hh:1490: error: ISO C++ says that these are
+    ambiguous, even though the worst conversion for the first is better
+    than the worst conversion for the second:
+    hb-iter.hh:63: note: candidate 1: Item& hb_iter_t<Iter,
+    Item>::operator[](unsigned int) const [with Iter = hb_array_t<const
+    OT::IntType<short unsigned int, 2u> >, Item = const OT::IntType<short
+    unsigned int, 2u>]
+    hb-ot-layout-common.hh:1490: note: candidate 2: operator[](T*,
+    int) <built-in>
+
+ src/hb-iter.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 25786f49c1df36fdb5f78681055a1f4aa4b17f86
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 19:29:00 2018 -0500
+
+    [array] Port to hb_iter_t<>
+
+    hb_array_t is its own iterator...
+
+ src/hb-array.hh | 75
+ +++++++++++++++++++++++++--------------------------------
+ src/hb-iter.hh  |  5 ++--
+ 2 files changed, 36 insertions(+), 44 deletions(-)
+
+commit 2a33ab0560a13cb8fef5983bfe0f6d68dfd47b14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 18:49:27 2018 -0500
+
+    [iter] Change __more__ to fallback to __len__
+
+ src/hb-iter.hh   | 15 ++++++---------
+ src/test-iter.cc |  1 -
+ 2 files changed, 6 insertions(+), 10 deletions(-)
+
+commit 474a12058d681f2d7cef84db0cf20f9f784fa400
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 18:46:51 2018 -0500
+
+    [array/vector] Rename len to length
+
+ src/hb-aat-layout-feat-table.hh |  5 ++-
+ src/hb-aat-layout-lcar-table.hh |  2 +-
+ src/hb-aat-map.cc               |  4 +--
+ src/hb-array.hh                 | 72
+ ++++++++++++++++++++---------------------
+ src/hb-cff-interp-common.hh     | 10 +++---
+ src/hb-cff2-interp-cs.hh        |  6 ++--
+ src/hb-coretext.cc              | 12 +++----
+ src/hb-face.cc                  |  4 +--
+ src/hb-object.hh                | 23 +++++++------
+ src/hb-open-file.hh             |  4 +--
+ src/hb-open-type.hh             |  8 ++---
+ src/hb-ot-cff-common.hh         | 38 +++++++++++-----------
+ src/hb-ot-cff1-table.hh         | 28 ++++++++--------
+ src/hb-ot-cmap-table.hh         | 24 +++++++-------
+ src/hb-ot-color-colr-table.hh   |  6 ++--
+ src/hb-ot-hdmx-table.hh         |  6 ++--
+ src/hb-ot-hmtx-table.hh         |  8 ++---
+ src/hb-ot-layout-common.hh      | 32 +++++++++---------
+ src/hb-ot-layout-gdef-table.hh  |  4 +--
+ src/hb-ot-layout-gsub-table.hh  | 24 +++++++-------
+ src/hb-ot-layout-gsubgpos.hh    |  2 +-
+ src/hb-ot-layout.cc             |  2 +-
+ src/hb-ot-map.cc                | 22 ++++++-------
+ src/hb-ot-map.hh                |  4 +--
+ src/hb-ot-math-table.hh         |  4 +--
+ src/hb-ot-maxp-table.hh         |  2 +-
+ src/hb-ot-name-table.hh         |  8 ++---
+ src/hb-ot-name.cc               |  4 +--
+ src/hb-ot-post-table.hh         |  8 ++---
+ src/hb-ot-var-fvar-table.hh     |  2 +-
+ src/hb-ot-vorg-table.hh         | 10 +++---
+ src/hb-set.hh                   | 36 ++++++++++-----------
+ src/hb-subset-cff-common.cc     |  8 ++---
+ src/hb-subset-cff-common.hh     | 50 ++++++++++++++--------------
+ src/hb-subset-cff1.cc           | 48 +++++++++++++--------------
+ src/hb-subset-cff2.cc           | 16 ++++-----
+ src/hb-subset-glyf.cc           | 14 ++++----
+ src/hb-subset-plan.cc           |  2 +-
+ src/hb-uniscribe.cc             | 26 +++++++--------
+ src/hb-vector.hh                | 56 ++++++++++++++++----------------
+ src/test-iter.cc                |  4 +--
+ 41 files changed, 325 insertions(+), 323 deletions(-)
+
+commit 2fc1860a5b40f5deba720c0c1099fdd0450b77c0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 18:09:45 2018 -0500
+
+    [iter] Split hb_iter_t<> into hb_iter_t<> and hb_iter_mixin_t<>
+
+ src/hb-iter.hh   | 31 ++++++++++++++++++++-----------
+ src/test-iter.cc |  2 +-
+ 2 files changed, 21 insertions(+), 12 deletions(-)
+
+commit 865deeb3be1cb40efe3d7c42db48b0cdf977de47
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 17:35:58 2018 -0500
+
+    Adjust internal header dependencies
+
+ src/hb-array.hh            |  5 ++++-
+ src/hb-dsalgs.hh           |  1 -
+ src/hb-iter.hh             |  1 +
+ src/hb-vector.hh           |  1 +
+ src/hb.hh                  | 15 +++++++++------
+ src/test-iter.cc           |  1 +
+ src/test-unicode-ranges.cc |  1 +
+ 7 files changed, 17 insertions(+), 8 deletions(-)
+
+commit 8e5c2bc60bd9a800dacc96cc29c6ff831a852ae3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 17:29:11 2018 -0500
+
+    [Makefile.am] Minor
+
+ src/Makefile.am | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+commit f419cef4174c5447bf5031e771483f3274ae4dce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 17:22:09 2018 -0500
+
+    [iter] Include from hb.hh
+
+ src/hb.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 7557e34872c846433c2465b21b99bf7c5f961673
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 17:21:19 2018 -0500
+
+    [iter] Move hb_fill() and hb_copy() to hb-iter.hh
+
+ src/hb-iter.hh   | 18 ++++++++++++++++++
+ src/test-iter.cc | 16 ----------------
+ 2 files changed, 18 insertions(+), 16 deletions(-)
+
+commit 5e1840e031cff1127842fc5cc8ee93e5959f02d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 16:39:57 2018 -0500
+
+    [iter] Disallow copy-construction or assignment of hb_iter_t<>
+
+    Should only be done by subclass.
+
+ src/hb-iter.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 65e8bd56ad26912636fbdc400a83cc48db2a13ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 16:20:30 2018 -0500
+
+    [iter] Fix hb_copy() return value
+
+ src/test-iter.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 40d71211a8969ec4414d2476a209e60d0a3525d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 16:19:44 2018 -0500
+
+    [iter] Add const_iter_t / const_iter()
+
+ src/hb-iter.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit aaddfaa57a841726a8b49653af3f8b702831da1b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 16:04:38 2018 -0500
+
+    [iter] Make hb_fill() take collection type, not iter
+
+    Starting to get the hang of when take which.
+
+ src/test-iter.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 7b4eea853c36fd59db6e5d68bbef9b8cebad760e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 16:02:16 2018 -0500
+
+    [array] Add more hb_array() / hb_sorted_array() variants
+
+ src/hb-array.hh | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+commit 09740148e310021a4a690666c2e2836c2005353d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:56:01 2018 -0500
+
+    [serialize] Use component_list by reference, as a supplier
+
+ src/hb-ot-layout-gsub-table.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 3dbe1e364c19d82ab436b9ea7b41c9754d43e923
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:53:09 2018 -0500
+
+    [iter] Add .random_access()
+
+ src/hb-iter.hh   | 4 ++++
+ src/test-iter.cc | 1 +
+ 2 files changed, 5 insertions(+)
+
+commit 20f14b4aa6311d8fb2ed80c47bb15e8d87d2f6b3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:19:22 2018 -0500
+
+    [iter] Fix __end__()
+
+ src/hb-iter.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 95265aeab7da54f31d4f68590af7730054b6be16
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:12:55 2018 -0500
+
+    [array] Remove copy constructor
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1502
+
+ src/hb-array.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 69d232eaea323b8c42e5fa1788553ac4e8bf3a50
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:08:06 2018 -0500
+
+    Fix bot
+
+      C:\projects\harfbuzz\src\hb-uniscribe.cc(709): error C2666:
+      'hb_vector_t<OPENTYPE_FEATURE_RECORD,8>::operator
+      +': 3 overloads have similar conversions
+      [C:\projects\harfbuzz\build\harfbuzz.vcxproj]
+
+ src/hb-uniscribe.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b9a51f531009ce201b86a0326aff662fd19a68a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 15:05:00 2018 -0500
+
+    Minor
+
+ src/hb-ot-layout-gpos-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit bdb6da72267c8fa4802a2183ba69a1535653378b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 11:20:27 2018 -0500
+
+    [iter] Fix test again
+
+ src/test-iter.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit e9520752489298e0ce1a08da10ec3d439f9356d9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 11:15:16 2018 -0500
+
+    Minor
+
+ src/Makefile.am  | 6 +++---
+ src/test-iter.cc | 1 -
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+commit 35503d7d7324293162b605ffe0bd712656dd52b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 03:03:46 2018 -0500
+
+    [iter] More prototyping
+
+ src/test-iter.cc | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+commit 73c7a896d1395539e3c9e71b073ce5094c835aa0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 02:48:28 2018 -0500
+
+    [iter] Make hb_fill() and hb_copy() take iterators
+
+    I'm still going back and force...
+
+ src/test-iter.cc | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+commit 12e506fda4bfd82d67e4beede29ae7dbc02ad8f4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 02:47:04 2018 -0500
+
+    [iter] Add hb_fill()
+
+ src/test-iter.cc | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+commit ad3ed58de5297930826c67d18b99991b93d29654
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 02:12:55 2018 -0500
+
+    [iter] Start prototyping hb_copy()
+
+ src/test-iter.cc | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+commit 44af738d19486095c0fbc2ef2b359a298126ac2b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 01:59:37 2018 -0500
+
+    [iter] Showcase implicit casts
+
+ src/test-iter.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 879faa2aee74e237594901426096ceeb78a716a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 01:57:40 2018 -0500
+
+    Rename
+
+ src/hb-array.hh     | 2 +-
+ src/hb-open-type.hh | 4 ++--
+ src/hb-vector.hh    | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+commit aeb696a91cd1cdc73bf5b87e56163c7f64778616
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 01:57:02 2018 -0500
+
+    [iter] Rename
+
+ src/hb-iter.hh | 44 ++++++++++++++++++++++----------------------
+ 1 file changed, 22 insertions(+), 22 deletions(-)
+
+commit 8001e00a470ad06f0307002b4cade5612ee7b521
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 01:53:27 2018 -0500
+
+    [iter] First sample use
+
+ src/Makefile.am  |  5 ++++-
+ src/hb-iter.hh   | 25 +++++++++++--------------
+ src/test-iter.cc | 25 ++++++++++++++++++++-----
+ 3 files changed, 35 insertions(+), 20 deletions(-)
+
+commit 19d2b5013d8ac7aa45b3b8e8c61ad90773c86925
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 01:17:35 2018 -0500
+
+    [iter] Add bidirectionality
+
+ src/hb-iter.hh | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+commit 314d8698d0746416efd332f5fae45aecb26df7ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 00:54:55 2018 -0500
+
+    [iter] Sketch new iterator design
+
+ src/hb-iter.hh   | 154
+ +++++++++++++++++++------------------------------------
+ src/test-iter.cc |  16 ++++++
+ 2 files changed, 69 insertions(+), 101 deletions(-)
+
+commit f6d5f1e91ced2b6b1114ad765f568f799dd3612f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 00:23:34 2018 -0500
+
+    [iter] Add empty test
+
+ src/Makefile.am            |  7 +++++--
+ src/hb-machinery.hh        |  1 -
+ src/test-iter.cc           | 33 +++++++++++++++++++++++++++++++++
+ src/test-unicode-ranges.cc |  2 --
+ 4 files changed, 38 insertions(+), 5 deletions(-)
+
+commit b80b97b549dacc10d314bf8b5fd4ace596ccdfe1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Dec 21 00:08:05 2018 -0500
+
+    Revert "Remove unused hb-iter.hh"
+
+    This reverts commit 969ff3c7aadbe721cdd414488eb170433f10d00c.
+
+ src/Makefile.sources |   1 +
+ src/hb-iter.hh       | 146
+ +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-machinery.hh  |   1 +
+ 3 files changed, 148 insertions(+)
+
+commit a728c63a98281fd4a0661e17fc01171bc3205b27
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 23:15:49 2018 -0500
+
+    [vector] Add operator bool
+
+ src/hb-vector.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit bd369773921b4891996bd21f325702e490f47ca4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 23:14:24 2018 -0500
+
+    Rename
+
+ src/hb-array.hh     | 2 +-
+ src/hb-open-type.hh | 4 ++--
+ src/hb-vector.hh    | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+commit e6ebc9b6f89e62d888b3bcf926afd624f16f3e95
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 23:13:36 2018 -0500
+
+    Remove unused typedef
+
+ src/hb-machinery.hh | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 4941e95f10fe0fe658752134a42b58896fb19c42
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 21:48:57 2018 -0500
+
+    2.3.0
+
+ NEWS                 | 15 +++++++++++++++
+ configure.ac         |  2 +-
+ src/hb-aat-layout.cc |  6 +++---
+ src/hb-version.h     |  4 ++--
+ 4 files changed, 21 insertions(+), 6 deletions(-)
+
+commit 87f7c83fffb7e64970be23c8e3c620d32a3b8f5b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 15:54:17 2018 -0500
+
+    [serializer] Add operator <<
+
+    Not sure if we are going to use it.  But might incentivize us to.
+
+ src/hb-machinery.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 5b70074edf1c12a9442037d54c03d3025bd93995
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 15:38:59 2018 -0500
+
+    Add hb_assign(obj, value)
+
+ src/hb-machinery.hh |  2 +-
+ src/hb-null.hh      | 24 +++++++++++++++++++++++-
+ src/hb-open-type.hh |  5 +++--
+ 3 files changed, 27 insertions(+), 4 deletions(-)
+
+commit 6124123393eabb77d34830c971ec463998d50aba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 12:26:30 2018 -0500
+
+    [serialize] Adjust ClassDef
+
+    [skip ci]
+
+ src/hb-ot-layout-common.hh | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+commit 4220b7bdd7706622563401bf8f055c4b1482b4e5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 20 11:48:45 2018 -0500
+
+    Fix code on big-endian gcc / clang
+
+    Ouch!  We need a bigendian bot...
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1498
+
+ src/hb-machinery.hh | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit c87ee72232416099a73b563ca7aaf293b1c87b2a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 19 22:28:16 2018 -0500
+
+    Minor [skip ci]
+
+ src/hb-dsalgs.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 5000a59a6391d588c2cbdda132839b1fb1f75bf2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 19 21:07:53 2018 -0500
+
+    [saitnize] Minor
+
+ src/hb-machinery.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 3ee4ea945674c4b96c9aa6b0367bbf22dc8745d1
+Author: fanc999 <fanc999@yahoo.com.tw>
+Date:   Thu Dec 20 11:26:54 2018 +0800
+
+    Fix build on older Visual Studio versions (#1499)
+
+    * src/hb-cff-interp-dict-common.hh: Use ull for unsigned int64_t
+
+    The llu suffix does not work for older Visual Studio versions
+    (pre-2013), but ull works for all the compilers that we attempt to
+    support.
+
+    * test/api: Fix build on pre-C99 compilers
+
+    Ensure variables are declared at the top of the block.
+
+    * src/hb-dsalgs.hh: Add specialization for hb_is_signed<> for __int8
+
+    Pre-Visual Studio 2010 does not consider __int8 (which is typedef'ed
+    to
+    int8_t) to be equivilant to signed char, so the compiler cannot
+    find the
+    corresponding hb_is_signed<> specialization that is needed.
+
+    The interesting thing is unsigned __int8 is considered to be
+    equivilant
+    to unsigned char, so as the other types (short, int, long) that
+    we look
+    for here, so only the specialization for __int8 is added here.
+
+    This will fix builds on Visual Studio 2008 at least.
+
+ src/hb-cff-interp-dict-common.hh |  2 +-
+ src/hb-dsalgs.hh                 |  9 +++++++++
+ test/api/test-aat-layout.c       |  3 ++-
+ test/api/test-subset-cff1.c      | 12 ++++++++----
+ 4 files changed, 20 insertions(+), 6 deletions(-)
+
+commit a62870506d16949582bf0b54e3dc8846b9747a4a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 19 21:05:00 2018 -0500
+
+    [sanitize] Use hb_static_size instead of ::static_size
+
+    https://github.com/harfbuzz/harfbuzz/issues/1496#issuecomment-448818112
+
+ src/hb-machinery.hh | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+commit 0c9cd5d5f4d96df77e4298e16c786e67b83f9bc4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 19 21:18:30 2018 +0330
+
+    [test] Fix test-name-table.cc leak issue
+
+    Spotted it accidentally but wanted to see if is anything serious so
+    went for fixing it
+
+ src/test-name-table.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 3d9d7dc4dd4be8e746507282569504b511afa709
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 18 22:11:23 2018 -0500
+
+    [arrays] Add hb_ubytes_t for unsigned char
+
+ src/hb-array.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit f1e95e40edc871c840abe8a8a695efc252af40f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 18 16:49:08 2018 -0500
+
+    [arrays] Remove hb_supplier_t<>
+
+ src/hb-array.hh                            |  11 --
+ src/hb-cff2-interp-cs.hh                   |   2 +-
+ src/hb-face.cc                             |   6 +-
+ src/hb-open-file.hh                        |  15 +-
+ src/hb-open-type.hh                        |  18 +-
+ src/hb-ot-cmap-table.hh                    |   3 +-
+ src/hb-ot-layout-common.hh                 | 104 ++++--------
+ src/hb-ot-layout-gsub-table.hh             | 257
+ +++++++++++++----------------
+ src/hb-ot-shape-complex-arabic-fallback.hh |  23 +--
+ 9 files changed, 170 insertions(+), 269 deletions(-)
+
+commit f9417af29bd5a1d2f5b55389a1cc6f4280b347d8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 18 13:23:32 2018 -0500
+
+    [serialize] Propagate error from hb-face
+
+ src/hb-face.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 9aebfb418222427a324d911b32abfc11256ca9e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 18 13:22:17 2018 -0500
+
+    [serialize] Streamline error propagation
+
+ src/hb-buffer.hh               |  2 ++
+ src/hb-machinery.hh            | 35 ++++++++++++++++++++++++++---------
+ src/hb-map.hh                  |  2 ++
+ src/hb-ot-layout-common.hh     |  4 ++--
+ src/hb-ot-layout-gsub-table.hh |  4 ++--
+ src/hb-set.hh                  |  2 ++
+ src/hb-subset.cc               |  2 +-
+ 7 files changed, 37 insertions(+), 14 deletions(-)
+
+commit 969ff3c7aadbe721cdd414488eb170433f10d00c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 22:43:00 2018 -0500
+
+    Remove unused hb-iter.hh
+
+    The ideas there are all part of hb-array.hh now.  To be determined
+    how we
+    want to use generic iterator patterns.
+
+ src/Makefile.sources |   1 -
+ src/hb-iter.hh       | 146
+ ---------------------------------------------------
+ src/hb-machinery.hh  |   1 -
+ 3 files changed, 148 deletions(-)
+
+commit b1094fc2d2b614c1407b502d15bd98407a5ffb56
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 22:41:04 2018 -0500
+
+    [arrays] Minor tweaks to hb_supplier_t
+
+    I think I like to keep this hb_supplier_t thing separately from
+    hb_array_t.
+
+ src/hb-array.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit cf39c242057636feebafce347f8e7ac2b305112a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 22:36:23 2018 -0500
+
+    [arrays] Rename Supplier to hb_supplier_t
+
+ src/hb-array.hh                            |   6 +-
+ src/hb-face.cc                             |   2 +-
+ src/hb-open-file.hh                        |   4 +-
+ src/hb-open-type.hh                        |   4 +-
+ src/hb-ot-cmap-table.hh                    |   2 +-
+ src/hb-ot-layout-common.hh                 |  34 ++++-----
+ src/hb-ot-layout-gsub-table.hh             | 108
+ ++++++++++++++---------------
+ src/hb-ot-shape-complex-arabic-fallback.hh |  14 ++--
+ 8 files changed, 87 insertions(+), 87 deletions(-)
+
+commit 6b5eaa753047b6b0389cb7521c52efbaccf72daf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 21:55:33 2018 -0500
+
+    Hide hb_addressof()
+
+ src/hb-dsalgs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6befa75cdf83d561de69fb342f68694cd7b46f5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 20:34:51 2018 -0500
+
+    Enable __builtin_* on clang
+
+    We'll see which old clang versions this breaks...
+
+ src/hb-dsalgs.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 8d2d41025619e24160ed80edd1c413168a2dda36
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 20:23:26 2018 -0500
+
+    Add hb_addressof() and use it to fix bug after hb_bytes_t merge
+
+    We cannot take address hb_bytes_t direction.  We need to use the
+    newly added hb_addressof(), ala std::addressof().
+
+ src/hb-dsalgs.hh        | 9 +++++++++
+ src/hb-ot-post-table.hh | 3 ++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+commit 49334f9b509fc15e8baa93d49b86886ca933de04
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 18:27:36 2018 -0500
+
+    Enable system extensions in hb.hh
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1491
+
+ configure.ac |  1 -
+ src/hb.hh    | 26 ++++++++++++++++++++++++++
+ 2 files changed, 26 insertions(+), 1 deletion(-)
+
+commit 37c14bc7459e8b9cc0840b68223123ffb950b4cc
+Author: prrace <philip.race@oracle.com>
+Date:   Mon Dec 17 14:59:37 2018 -0800
+
+    Fix Solaris use after free (#1495)
+
+ src/hb-atomic.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 483f2491e40ccf660836ed2797738297e40bd100
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 17:56:10 2018 -0500
+
+    Remove define GNU_SOURCE
+
+    Not needed.  We get it in our config.h automatically thanks to
+    AC_USE_SYSTEM_EXTENSIONS.  Let's see whose build it breaks...
+    If we end up putting it back, we should add other things from
+    that macro and remove the macro.
+
+ src/hb.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 87ff65aea117391c732d51d874964b3e32d6fa94
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 17:19:42 2018 -0500
+
+    Fix more warnings
+
+ src/hb.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f9d219a17417f61fa2c6152d2181504866583a72
+Author: prrace <philip.race@oracle.com>
+Date:   Mon Dec 17 14:18:47 2018 -0800
+
+    Fix Solaris Trailing comma in enum warnings (#1490)
+
+ src/hb-ot-color.h | 2 +-
+ src/hb-ot-name.h  | 2 +-
+ src/hb-ot-var.h   | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 244a8627f7b0ed651d6010c7ee7e54fa8fcca400
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Dec 17 21:31:43 2018 +0330
+
+    Lower coretext_aat shaper priority (#1488)
+
+    Related to https://github.com/harfbuzz/harfbuzz/issues/1478
+
+ src/hb-shaper-list.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit e41200859997ccf8fd7d36fff654f3ceea3a4160
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Dec 17 21:31:01 2018 +0330
+
+    Remove redundant void from C++ sources (#1486)
+
+ src/dump-indic-data.cc           |   2 +-
+ src/dump-khmer-data.cc           |   2 +-
+ src/dump-myanmar-data.cc         |   2 +-
+ src/dump-use-data.cc             |   2 +-
+ src/hb-aat-fdsc-table.hh         |   4 +-
+ src/hb-aat-layout-common.hh      |  23 +++---
+ src/hb-aat-layout-feat-table.hh  |   8 +--
+ src/hb-aat-layout-just-table.hh  |   2 +-
+ src/hb-aat-layout-kerx-table.hh  |  21 +++---
+ src/hb-aat-layout-morx-table.hh  |  10 +--
+ src/hb-aat-layout-trak-table.hh  |   4 +-
+ src/hb-aat-layout.cc             |   6 +-
+ src/hb-aat-map.hh                |   4 +-
+ src/hb-array.hh                  |  24 +++----
+ src/hb-atomic.hh                 |  18 ++---
+ src/hb-blob.cc                   |   8 +--
+ src/hb-blob.hh                   |  33 ++++-----
+ src/hb-buffer-serialize.cc       |   2 +-
+ src/hb-buffer.cc                 |  24 +++----
+ src/hb-buffer.hh                 |  51 ++++++-------
+ src/hb-cache.hh                  |   6 +-
+ src/hb-cff-interp-common.hh      | 113 +++++++++++++----------------
+ src/hb-cff-interp-cs-common.hh   |  26 +++----
+ src/hb-cff-interp-dict-common.hh |  12 ++--
+ src/hb-cff1-interp-cs.hh         |   4 +-
+ src/hb-cff2-interp-cs.hh         |  24 +++----
+ src/hb-common.cc                 |  20 +++---
+ src/hb-coretext.cc               |   2 +-
+ src/hb-debug.hh                  |   6 +-
+ src/hb-directwrite.cc            |  16 ++---
+ src/hb-dsalgs.hh                 |   2 +-
+ src/hb-face.cc                   |   6 +-
+ src/hb-face.hh                   |   8 +--
+ src/hb-font.cc                   |   6 +-
+ src/hb-font.hh                   |   6 +-
+ src/hb-ft.cc                     |  18 ++---
+ src/hb-glib.cc                   |   8 +--
+ src/hb-gobject-enums.cc.tmpl     |   2 +-
+ src/hb-gobject-enums.h.tmpl      |   2 +-
+ src/hb-gobject-structs.cc        |   2 +-
+ src/hb-icu.cc                    |   8 +--
+ src/hb-iter.hh                   |  15 ++--
+ src/hb-machinery.hh              | 150
+ ++++++++++++++++-----------------------
+ src/hb-map.cc                    |   4 +-
+ src/hb-map.hh                    |  24 +++----
+ src/hb-mutex.hh                  |  10 +--
+ src/hb-null.hh                   |  32 ++++-----
+ src/hb-object.hh                 |  22 +++---
+ src/hb-open-file.hh              |  32 ++++-----
+ src/hb-open-type.hh              |  66 +++++++++--------
+ src/hb-ot-cff-common.hh          |  30 ++++----
+ src/hb-ot-cff1-table.cc          |  17 ++---
+ src/hb-ot-cff1-table.hh          |  52 ++++++--------
+ src/hb-ot-cff2-table.cc          |   8 +--
+ src/hb-ot-cff2-table.hh          |  34 ++++-----
+ src/hb-ot-cmap-table.hh          |  10 +--
+ src/hb-ot-color-cbdt-table.hh    |   4 +-
+ src/hb-ot-color-colr-table.hh    |   2 +-
+ src/hb-ot-color-cpal-table.hh    |  10 +--
+ src/hb-ot-color-sbix-table.hh    |  11 ++-
+ src/hb-ot-color-svg-table.hh     |   7 +-
+ src/hb-ot-face.cc                |   2 +-
+ src/hb-ot-face.hh                |   2 +-
+ src/hb-ot-font.cc                |   8 +--
+ src/hb-ot-glyf-table.hh          |   6 +-
+ src/hb-ot-hdmx-table.hh          |   4 +-
+ src/hb-ot-head-table.hh          |   8 +--
+ src/hb-ot-hmtx-table.hh          |   2 +-
+ src/hb-ot-kern-table.hh          |  20 +++---
+ src/hb-ot-layout-base-table.hh   |  10 +--
+ src/hb-ot-layout-common.hh       |  67 +++++++++--------
+ src/hb-ot-layout-gdef-table.hh   |  20 +++---
+ src/hb-ot-layout-gpos-table.hh   |  34 ++++-----
+ src/hb-ot-layout-gsub-table.hh   |  24 +++----
+ src/hb-ot-layout-gsubgpos.hh     |  92 +++++++++++-------------
+ src/hb-ot-layout-jstf-table.hh   |   8 +--
+ src/hb-ot-map.cc                 |   2 +-
+ src/hb-ot-map.hh                 |   8 +--
+ src/hb-ot-math-table.hh          |  11 ++-
+ src/hb-ot-maxp-table.hh          |   5 +-
+ src/hb-ot-name-table.hh          |   6 +-
+ src/hb-ot-os2-table.hh           |  18 ++---
+ src/hb-ot-post-table.hh          |   4 +-
+ src/hb-ot-shape.cc               |   2 +-
+ src/hb-ot-shape.hh               |   2 +-
+ src/hb-ot-tag.cc                 |   4 +-
+ src/hb-ot-var-fvar-table.hh      |   9 ++-
+ src/hb-ot-var-hvar-table.hh      |   9 +--
+ src/hb-ot-vorg-table.hh          |   2 +-
+ src/hb-set-digest.hh             |   4 +-
+ src/hb-set.cc                    |   4 +-
+ src/hb-set.hh                    |  38 +++++-----
+ src/hb-shape-plan.cc             |   2 +-
+ src/hb-shape-plan.hh             |   5 +-
+ src/hb-shape.cc                  |  10 +--
+ src/hb-shaper.cc                 |  14 ++--
+ src/hb-shaper.hh                 |   6 +-
+ src/hb-static.cc                 |   4 +-
+ src/hb-subset-cff-common.hh      |  91 +++++++++++-------------
+ src/hb-subset-cff1.cc            |  20 ++----
+ src/hb-subset-cff2.cc            |   8 +--
+ src/hb-subset-input.cc           |   2 +-
+ src/hb-subset.hh                 |   4 +-
+ src/hb-ucdn.cc                   |  10 +--
+ src/hb-unicode.cc                |  64 ++++++++---------
+ src/hb-uniscribe.cc              |  12 ++--
+ src/hb-vector.hh                 |  38 +++++-----
+ src/hb.hh                        |   6 +-
+ src/test-unicode-ranges.cc       |   4 +-
+ util/ansi-print.cc               |   6 +-
+ util/hb-fc.cc                    |   2 +-
+ util/hb-shape.cc                 |   5 +-
+ util/helper-cairo.cc             |   2 +-
+ util/helper-cairo.hh             |   2 +-
+ util/main-font-text.hh           |   2 +-
+ util/options.cc                  |   8 +--
+ util/options.hh                  |  22 +++---
+ util/view-cairo.hh               |  14 ++--
+ 118 files changed, 861 insertions(+), 1024 deletions(-)
+
+commit 7ace10078c23d00da4af0480f91b877faeed3d38
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Dec 17 20:07:04 2018 +0330
+
+    Minor, fix two more ArrayOf incorrect operator logic
+
+ src/hb-open-type.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a1240383aa82fd88e922a1e751444d14033ae882
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 10:44:14 2018 -0500
+
+    [arrays] Minor fix
+
+ src/hb-open-type.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 381c3548e9022a421bcf88db148cc11f337f3b79
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:39:30 2018 -0500
+
+    [array] Add cast operator to add const to Type
+
+    In lieu of constructor removed in previous commit.
+
+ src/hb-array.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 15acf33c228e0c8e0f8cc6a04e566970164dd5f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:38:13 2018 -0500
+
+    [array] Remove problematic constructor
+
+ src/hb-array.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 470369a871791b610e0c42212558e83baeb83409
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:20:19 2018 -0500
+
+    [array] Add arithmetic operators
+
+ src/hb-array.hh | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+commit 6cd60c2f2aa17e3f02b50c19cf640b3f183f3354
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:09:06 2018 -0500
+
+    [array] Return Crap instead of Null if Type is not const
+
+    Ouch!
+
+ src/hb-array.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 94e72cf1c9af563fbf522efb7f2e0b1fcd616418
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:06:40 2018 -0500
+
+    [array] Add operator *
+
+ src/hb-array.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 68d4a5eee0f248891d20d69b897201d105951aef
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 17 00:02:42 2018 -0500
+
+    [array] Add constructor from fixed-size array
+
+ src/hb-array.hh | 1 +
+ src/hb-iter.hh  | 4 ++--
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit a4354d2fd36377ec8b544c7b88a231cb1273dccd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:57:27 2018 -0500
+
+    [array] Organize
+
+ src/hb-array.hh | 75
+ ++++++++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 48 insertions(+), 27 deletions(-)
+
+commit 84c1865821151d83a8798ae11ebba3329a12c560
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:52:17 2018 -0500
+
+    [arrays] Reduce Supplier<> even further
+
+ src/hb-array.hh | 24 +++---------------------
+ 1 file changed, 3 insertions(+), 21 deletions(-)
+
+commit 1bcc4fc9f34ab518fc822c9464a73ba3e90f5f1c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:47:56 2018 -0500
+
+    Whitespace
+
+ src/hb-ot-shape-complex-arabic-fallback.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit f85f6e815f439075f8c6f5391e5c8dfe77e0f00d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:45:07 2018 -0500
+
+    [array] Add operator +=
+
+ src/hb-array.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 7c0e3e9b2b077fced829a10f616ed3d6b51c15c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:43:17 2018 -0500
+
+    [array] Add constructor from hb_array_t<const Type>
+
+ src/hb-array.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 92680361ec68734ad38e2158626feebaf18eec88
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:38:51 2018 -0500
+
+    [arrays] Move Supplier<> to hb-array.hh
+
+ src/hb-array.hh     | 33 +++++++++++++++++++++++++++++++++
+ src/hb-machinery.hh | 32 --------------------------------
+ 2 files changed, 33 insertions(+), 32 deletions(-)
+
+commit 2a3fa3f82ffdb778a2d21fc01e859579161237c9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:33:03 2018 -0500
+
+    [arrays] Remove unnecessary constructor from Supplier<>
+
+    Looks like operator hb_array_t<> from vector works here. :)
+
+ src/hb-machinery.hh | 5 -----
+ 1 file changed, 5 deletions(-)
+
+commit 507cac4943e987879b95d842fe60643abbf22efa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 23:31:19 2018 -0500
+
+    [arrays] Start moving Supplier<> to hb_array_t<>
+
+ src/hb-machinery.hh | 31 +++++++++++--------------------
+ 1 file changed, 11 insertions(+), 20 deletions(-)
+
+commit 1e2c98126e8500ace31483b05d77478afd59bab8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 22:30:44 2018 -0500
+
+    [arrays] Remove unused stride from Supplier
+
+ src/hb-machinery.hh | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+commit 0d0fe9df46c645538feaee1ec99a0108383a3669
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 22:29:40 2018 -0500
+
+    [arrays] Remove need of stride in Supplier<>
+
+ src/hb-face.cc      |  6 ++----
+ src/hb-open-file.hh | 19 +++++++++----------
+ src/hb-vector.hh    |  2 +-
+ 3 files changed, 12 insertions(+), 15 deletions(-)
+
+commit dcfa4a8d711716de88b94a370663e9564e3e7ccc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 20:40:07 2018 -0500
+
+    [array] Remove custom hb_bytes_t implementation
+
+ src/hb-array.hh         | 67
+ +++++++++++++++++--------------------------------
+ src/hb-machinery.hh     |  2 +-
+ src/hb-ot-name-table.hh |  8 +++---
+ src/hb-ot-name.cc       | 10 ++++----
+ 4 files changed, 33 insertions(+), 54 deletions(-)
+
+commit 3656f56d47cf6b89a25990d7836704fef79fa5b4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 20:35:11 2018 -0500
+
+    [arrays] Minor
+
+ src/hb-array.hh     |  3 ++-
+ src/hb-open-type.hh | 10 ++++------
+ src/hb-vector.hh    |  4 +---
+ 3 files changed, 7 insertions(+), 10 deletions(-)
+
+commit aa8f94714ee720c56be1a3406df7bacb0550158c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 20:20:35 2018 -0500
+
+    [array] Minor
+
+ src/hb-array.hh | 4 ++++
+ src/hb-iter.hh  | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit 5a552f75468d777d8d4bd3168e28f56a3369eafd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 20:07:44 2018 -0500
+
+    [array] Move hb_array_t and related types to hb-array.hh
+
+ src/Makefile.sources |   1 +
+ src/hb-array.hh      | 241
+ +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-dsalgs.hh     | 206 -------------------------------------------
+ src/hb-machinery.hh  |   1 +
+ src/hb-vector.hh     |   2 +-
+ 5 files changed, 244 insertions(+), 207 deletions(-)
+
+commit 01d06e34ffa746d3737df00bb692cdb1e859c1c6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 16 14:27:43 2018 -0500
+
+    Minor change to explicit_operator aesthetics
+
+ src/hb-iter.hh      | 2 +-
+ src/hb-machinery.hh | 2 +-
+ src/hb-vector.hh    | 4 ++--
+ src/hb.hh           | 4 ++--
+ 4 files changed, 6 insertions(+), 6 deletions(-)
+
+commit b2ebaa9afac0f57006283db92d1f3b4df3d6bd7e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Dec 16 22:38:10 2018 +0330
+
+    Remove redundant 'inline' from methods (#1483)
+
+ src/hb-aat-fdsc-table.hh         |  12 +-
+ src/hb-aat-layout-ankr-table.hh  |  12 +-
+ src/hb-aat-layout-bsln-table.hh  |  13 +-
+ src/hb-aat-layout-common.hh      | 150 +++++++-------
+ src/hb-aat-layout-feat-table.hh  |  46 ++---
+ src/hb-aat-layout-just-table.hh  |  26 +--
+ src/hb-aat-layout-kerx-table.hh  | 120 +++++------
+ src/hb-aat-layout-lcar-table.hh  |  14 +-
+ src/hb-aat-layout-morx-table.hh  | 104 +++++-----
+ src/hb-aat-layout-trak-table.hh  |  28 +--
+ src/hb-aat-layout.hh             |   2 +-
+ src/hb-aat-ltag-table.hh         |   6 +-
+ src/hb-aat-map.hh                |   7 +-
+ src/hb-atomic.hh                 |  26 +--
+ src/hb-blob.hh                   |  32 ++-
+ src/hb-buffer.hh                 |  76 ++++---
+ src/hb-cache.hh                  |  10 +-
+ src/hb-cff-interp-common.hh      | 197 +++++++++---------
+ src/hb-cff-interp-cs-common.hh   | 166 +++++++--------
+ src/hb-cff-interp-dict-common.hh |  26 +--
+ src/hb-cff1-interp-cs.hh         |  21 +-
+ src/hb-cff2-interp-cs.hh         |  48 ++---
+ src/hb-common.cc                 |  13 +-
+ src/hb-debug.hh                  |  20 +-
+ src/hb-directwrite.cc            |   2 +-
+ src/hb-dsalgs.hh                 |  84 ++++----
+ src/hb-face.cc                   |   2 +-
+ src/hb-face.hh                   |   6 +-
+ src/hb-font.hh                   | 216 ++++++++++----------
+ src/hb-ft.cc                     |   8 +-
+ src/hb-glib.cc                   |   2 +-
+ src/hb-icu.cc                    |   2 +-
+ src/hb-iter.hh                   |  18 +-
+ src/hb-kern.hh                   |   8 +-
+ src/hb-machinery.hh              | 210 +++++++++----------
+ src/hb-map.hh                    |  38 ++--
+ src/hb-mutex.hh                  |  12 +-
+ src/hb-null.hh                   |  26 +--
+ src/hb-object.hh                 |  34 ++--
+ src/hb-open-file.hh              |  92 ++++-----
+ src/hb-open-type.hh              | 253 ++++++++++++-----------
+ src/hb-ot-cff-common.hh          | 177 ++++++++--------
+ src/hb-ot-cff1-table.cc          |  32 +--
+ src/hb-ot-cff1-table.hh          | 160 +++++++--------
+ src/hb-ot-cff2-table.cc          |  16 +-
+ src/hb-ot-cff2-table.hh          |  62 +++---
+ src/hb-ot-cmap-table.hh          | 185 +++++++++--------
+ src/hb-ot-color-cbdt-table.hh    |  40 ++--
+ src/hb-ot-color-colr-table.hh    |  18 +-
+ src/hb-ot-color-cpal-table.hh    |  55 +++--
+ src/hb-ot-color-sbix-table.hh    |  48 ++---
+ src/hb-ot-color-svg-table.hh     |  20 +-
+ src/hb-ot-font.cc                |   2 +-
+ src/hb-ot-gasp-table.hh          |   6 +-
+ src/hb-ot-glyf-table.hh          |  37 ++--
+ src/hb-ot-hdmx-table.hh          |  36 ++--
+ src/hb-ot-head-table.hh          |  10 +-
+ src/hb-ot-hhea-table.hh          |   2 +-
+ src/hb-ot-hmtx-table.hh          |  18 +-
+ src/hb-ot-kern-table.hh          |  44 ++--
+ src/hb-ot-layout-base-table.hh   | 104 +++++-----
+ src/hb-ot-layout-common.hh       | 425
+ ++++++++++++++++++++-------------------
+ src/hb-ot-layout-gdef-table.hh   | 126 ++++++------
+ src/hb-ot-layout-gpos-table.hh   | 209 +++++++++----------
+ src/hb-ot-layout-gsub-table.hh   | 360 ++++++++++++++++-----------------
+ src/hb-ot-layout-gsubgpos.hh     | 353 ++++++++++++++++----------------
+ src/hb-ot-layout-jstf-table.hh   |  44 ++--
+ src/hb-ot-map.hh                 |  38 ++--
+ src/hb-ot-math-table.hh          | 142 ++++++-------
+ src/hb-ot-maxp-table.hh          |  12 +-
+ src/hb-ot-name-table.hh          |  21 +-
+ src/hb-ot-os2-table.hh           |  34 ++--
+ src/hb-ot-post-table.hh          |  26 +--
+ src/hb-ot-shape-complex-indic.cc |  10 +-
+ src/hb-ot-shape-complex-khmer.cc |  10 +-
+ src/hb-ot-shape.hh               |   6 +-
+ src/hb-ot-stat-table.hh          |  16 +-
+ src/hb-ot-var-avar-table.hh      |   8 +-
+ src/hb-ot-var-fvar-table.hh      |  55 +++--
+ src/hb-ot-var-hvar-table.hh      |  16 +-
+ src/hb-ot-var-mvar-table.hh      |  10 +-
+ src/hb-ot-vorg-table.hh          |  22 +-
+ src/hb-set-digest.hh             |  41 ++--
+ src/hb-set.hh                    | 114 +++++------
+ src/hb-shape.cc                  |  14 +-
+ src/hb-shaper.cc                 |  14 +-
+ src/hb-shaper.hh                 |  10 +-
+ src/hb-subset-cff-common.hh      | 175 ++++++++--------
+ src/hb-subset-cff1.cc            |  91 ++++-----
+ src/hb-subset-cff2.cc            |  36 ++--
+ src/hb-subset-plan.hh            |  12 +-
+ src/hb-subset.hh                 |   4 +-
+ src/hb-ucdn.cc                   |   2 +-
+ src/hb-unicode.hh                |  26 +--
+ src/hb-uniscribe.cc              |  16 +-
+ src/hb-utf.hh                    |  54 +++--
+ src/hb-vector.hh                 |  86 ++++----
+ 97 files changed, 2911 insertions(+), 2987 deletions(-)
+
+commit 7251c7729061b7df29efe2b466315e96c81ad03f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 15 21:00:55 2018 -0500
+
+    Whitespace
+
+ src/hb-buffer-serialize.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 829b56b1a22736eac49132b2e56dc480157afca2
+Author: Behdad Esfahbod <behdad@google.com>
+Date:   Sat Dec 15 13:02:13 2018 -0500
+
+    Whitespace
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 42a1012562c1f020f470526a34b68ed21ad138cc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 19:39:59 2018 -0500
+
+    [subset] Actually subset GDEF
+
+ src/hb-subset.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit c9c746c7f6091e575fd74ba8f8cae2c4fd44a1ad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 18:37:37 2018 -0500
+
+    [subset] Fix up ClassDef some more
+
+ src/hb-ot-layout-common.hh | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+commit 7ee6128902333716dd8d8df6e38a8d1ebacb0a46
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 18:32:04 2018 -0500
+
+    [subset] Fix ClassDefFormat1 subsetting
+
+ src/hb-ot-layout-common.hh | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+commit 1b6d0c44b3067f5840d3fdac99fbc7448d0f37bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 18:10:48 2018 -0500
+
+    [subset] Sketch GDEF subsetting
+
+ src/hb-ot-layout-gdef-table.hh | 20 ++++++++++++++++++++
+ src/hb-ot-layout-gsubgpos.hh   |  2 ++
+ 2 files changed, 22 insertions(+)
+
+commit 705e2f5056d60c28154004e0c5d3b0ec67fe93c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 17:48:42 2018 -0500
+
+    [subset] Implement for ClassDef
+
+ src/hb-ot-layout-common.hh     | 80
+ ++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout-gsub-table.hh |  8 ++---
+ 2 files changed, 84 insertions(+), 4 deletions(-)
+
+commit 6e33a3955df77b9d1fda5ea44302d97b21e7871c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 16:40:01 2018 -0500
+
+    Minor
+
+ src/hb-machinery.hh            | 12 +++++++++---
+ src/hb-ot-cmap-table.hh        |  3 +--
+ src/hb-ot-layout-gsub-table.hh |  8 ++++----
+ 3 files changed, 14 insertions(+), 9 deletions(-)
+
+commit cc65901ca7185df926570d5067ace763a2cc759e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 16:01:45 2018 -0500
+
+    [serialize] Implement for ClassDef
+
+ src/hb-ot-layout-common.hh | 33 +++++++++++++++++++++++++++++++--
+ 1 file changed, 31 insertions(+), 2 deletions(-)
+
+commit e5309e4fd8583aa5c5ad9f3934d8aa593c850468
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 15:57:12 2018 -0500
+
+    [serialize] Implement for ClassDefFormat2
+
+ src/hb-ot-layout-common.hh | 50
+ ++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 46 insertions(+), 4 deletions(-)
+
+commit c8b43cbe316b07507aece4dc769f38226cd706da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 13 15:50:13 2018 -0500
+
+    [serialize] Implement for ClassDefFormat1
+
+ src/hb-ot-layout-common.hh | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+commit 576103132945c9d916514720d4034b398e099cfa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 21:21:26 2018 -0500
+
+    [subset] Minor
+
+ src/hb-subset.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 798e98c47bd9fa4d434487ae92e2c88ebb8a19a5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 12 18:08:15 2018 -0800
+
+    [CFF] bad offset in Index (#1476)
+
+    * Update hb-ot-cff-common.hh
+
+    * fix bug
+
+    * bummer fix wasn't hit. refix
+
+    * additional sanity check
+
+    * Added test cases for oss-fuzz issues 11805, 11806
+
+ src/hb-ot-cff-common.hh                                   |  10
+ ++++++++--
+ ...clusterfuzz-testcase-hb-subset-fuzzer-5643036478930944 | Bin 0 ->
+ 369 bytes
+ ...clusterfuzz-testcase-hb-subset-fuzzer-5686186874503168 | Bin 0 ->
+ 962 bytes
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+commit bcb4ecaf68c7219e89a801352bfc6a682b1581ef
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 12 17:36:01 2018 -0800
+
+    [CFF] check out of range FD index (#1477)
+
+    * add fd index checks to subr subsetter
+
+    also added oss-fuzz test case
+
+    * undid SubrSubsetParam::is_valid
+
+    because already validated by SubrClosures.valid
+
+ src/hb-subset-cff-common.hh                              |  10 ++++++++++
+ ...lusterfuzz-testcase-hb-subset-fuzzer-5762137968869376 | Bin 0 ->
+ 2037 bytes
+ 2 files changed, 10 insertions(+)
+
+commit 3f8e7a98d3cc10fefe65b9638c8abdf3ebe152cb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 11:32:57 2018 -0500
+
+    [util/hb-subset] Add --layout to keep GDEF/GSUB/GPOS
+
+    Will become default and option removed in the future.
+
+ util/hb-subset.cc | 1 +
+ util/options.cc   | 1 +
+ util/options.hh   | 2 ++
+ 3 files changed, 4 insertions(+)
+
+commit 2cc993e035cb37711f894968246817e53a9e823d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 10:07:38 2018 -0500
+
+    [dispatch] Minor
+
+ src/hb-ot-layout-gpos-table.hh | 4 +---
+ src/hb-ot-layout-gsub-table.hh | 4 +---
+ 2 files changed, 2 insertions(+), 6 deletions(-)
+
+commit 602fbfe3c96b3f18b0109239528ba18a19be4948
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 09:56:47 2018 -0500
+
+    [sanitize] Fix sanitizing sublookup array
+
+ src/hb-ot-layout-common.hh | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+commit c78e4784fbe06ceb27b54a1d8908016ade071cb4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 09:50:18 2018 -0500
+
+    [dispatch] Minor
+
+ src/hb-machinery.hh          | 1 +
+ src/hb-ot-layout-gsubgpos.hh | 3 ---
+ src/hb-subset.hh             | 1 -
+ 3 files changed, 1 insertion(+), 4 deletions(-)
+
+commit f9d211af1d6d78d092038d263b222ec8a65cf09d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 12 09:44:30 2018 -0500
+
+    Revert "Minor fix re sanitize of Lookup subtables"
+
+    This reverts commit 7146718bef81492e13aede0a2801cda1da41ce35.
+
+    Fixing differently.
+
+ src/hb-ot-layout-common.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 7ee5c52345c122436e054062084cd51292b90ad1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 12 15:14:37 2018 +0330
+
+    minor style fix, use void in methods on no argument
+
+ src/hb-aat-fdsc-table.hh        |   4 +-
+ src/hb-aat-layout-common.hh     |   6 +-
+ src/hb-aat-layout-feat-table.hh |   4 +-
+ src/hb-aat-layout-trak-table.hh |  18 +--
+ src/hb-aat-layout.cc            |   4 +-
+ src/hb-buffer.cc                |  48 +++----
+ src/hb-directwrite.cc           | 297
+ +++++++++++++++++++---------------------
+ src/hb-dsalgs.hh                |   5 +-
+ src/hb-map.hh                   |  20 +--
+ src/hb-ot-cmap-table.hh         |   2 +-
+ src/hb-ot-color-cbdt-table.hh   |   2 +-
+ src/hb-ot-color-cpal-table.hh   |   4 +-
+ src/hb-ot-color-sbix-table.hh   |  10 +-
+ src/hb-ot-color-svg-table.hh    |  15 +-
+ src/hb-ot-glyf-table.hh         |   2 +-
+ src/hb-ot-hdmx-table.hh         |   6 +-
+ src/hb-ot-layout-base-table.hh  |  11 +-
+ src/hb-ot-os2-table.hh          |  15 +-
+ 18 files changed, 211 insertions(+), 262 deletions(-)
+
+commit a33f238f8888cc969e1e393deda0518fb8dd6b13
+Merge: 7146718b 1e09add2
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 12 12:44:06 2018 +0330
+
+    Merge pull request #1474 from fanc999/master.msvc
+
+    Few fixes for Visual Studio builds
+
+commit 7146718bef81492e13aede0a2801cda1da41ce35
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 23:44:29 2018 -0500
+
+    Minor fix re sanitize of Lookup subtables
+
+    We were dereferencing Null pointers and trying to sanitize them,
+    which is not necessary...
+
+ src/hb-ot-layout-common.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit ce069d193229cde12c77a3f464fc10286bedf5f3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 23:07:48 2018 -0500
+
+    Minor
+
+ src/hb-open-type.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 1aea86944605e7e18acfd2c0a77ba60e62239274
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 22:53:58 2018 -0500
+
+    [subset] Map glyphs during SingleSubst subsetting
+
+    Ha!
+
+ src/hb-ot-layout-gsub-table.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 41d1a1c10f7e5ca69a337ae164d270e09b5f93ac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 22:48:27 2018 -0500
+
+    [subset] Minor
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2aba2c6c73301396f7e0e5dee819ab6863e74900
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 21:18:47 2018 -0500
+
+    [serialize] Break down assert
+
+ src/hb-machinery.hh | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+commit 9844c880e280e9cd28dcbeac2e581ac923c5ddf3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 11 17:28:04 2018 -0500
+
+    Minor
+
+ test/shaping/Makefile.am | 2 ++
+ util/Makefile.am         | 2 ++
+ 2 files changed, 4 insertions(+)
+
+commit 2941208f1eedabec2715b2a67d40f058df7eb5e6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 11 12:21:24 2018 -0800
+
+    [CFF] oss-fuzz issue 11690 ASSERT: substr.offset >= opStart (#1461)
+
+    * fix oss-fuzz 11690: substr.offset >= opStart
+
+    detect recursive subroutine call & handle as error
+
+    * fix build failure
+
+    * add minimized test case for oss-fuzz 11690
+
+    * removed asserts
+
+ src/hb-cff-interp-common.hh                             |   9 ++++-----
+ src/hb-subset-cff-common.hh                             |  12
+ ++++++++++--
+ src/hb-subset-cff1.cc                                   |   4 ++--
+ src/hb-subset-cff2.cc                                   |   4 ++--
+ ...testcase-minimized-hb-subset-fuzzer-5750420593442816 | Bin 0 ->
+ 96091 bytes
+ 5 files changed, 18 insertions(+), 11 deletions(-)
+
+commit 333586245cb37668c8a29af17920474c09667f4b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 11 12:20:20 2018 -0800
+
+    minimize use of assert: removed or changed to error handling (#1467)
+
+ src/hb-ot-cff-common.hh     |  2 +-
+ src/hb-ot-cff1-table.hh     | 12 ++++++++----
+ src/hb-subset-cff-common.cc |  6 ++++--
+ src/hb-subset-cff-common.hh |  1 -
+ src/hb-subset-cff1.cc       | 22 +++++++++++++++++-----
+ src/hb-subset-cff2.cc       | 14 +++++++++++---
+ 6 files changed, 41 insertions(+), 16 deletions(-)
+
+commit f24498c1e95e816889eb7a2f8b1062bbf15bed1b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Dec 11 23:02:52 2018 +0330
+
+    [ci] Fix Travis macOS bot ICU issue (#1472)
+
+ .travis.yml | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 9f3a51ddb952e1281f9a656fde7193c3e3b8dad2
+Author: 👻 <sarabi@Corsac-Fox.local>
+Date:   Tue Dec 11 13:38:05 2018 -0500
+
+    [ucdn] Fix header
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1470
+
+ src/hb-ucdn/ucdn.h | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit b225593d6baf3455e1ac951efc0df5015fdf7c69
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Tue Dec 11 13:19:17 2018 -0500
+
+    Correct REPLACEMENT CHARACTER's code point to FFFD (#1471)
+
+ test/shaping/hb_test_tools.py | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 1e09add232e14ef61d2f222a5ee05a2105af64f0
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Wed Dec 12 01:32:01 2018 +0800
+
+    test/api: Fix building on pre-C99 compilers
+
+    Ensure variables are declared at the top of the block.
+
+ test/api/hb-test.h         |  3 ++-
+ test/api/test-aat-layout.c |  3 ++-
+ test/api/test-font.c       |  2 +-
+ test/api/test-map.c        |  9 ++++++---
+ test/api/test-ot-color.c   |  9 +++++----
+ test/api/test-ot-face.c    | 14 ++++++++------
+ test/api/test-ot-name.c    | 30 ++++++++++++++++--------------
+ test/api/test-ot-tag.c     | 11 ++++++-----
+ 8 files changed, 46 insertions(+), 35 deletions(-)
+
+commit 09b16c536d31376de771eedde54620dd6c8f39d7
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Wed Dec 12 01:23:53 2018 +0800
+
+    CMake: Fix Introspection builds
+
+    We need to add -DHB_AAT_H and -DHB_AAT_H_IN to the flags that
+    are passed
+    to g-ir-scanner, so that introspection builds can proceed normally.
+
+ CMakeLists.txt | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 1683bb2c9337fa34e5e80d459ab5eab99d7a9804
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Dec 8 13:57:39 2018 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit f7cfe99815c07f82d5ad253af1e811db734bf92b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Dec 8 13:40:44 2018 +0330
+
+    [os2] Move typometrics detection logic to the table (#1465)
+
+ src/hb-ot-hmtx-table.hh | 14 +++++---------
+ src/hb-ot-os2-table.hh  |  7 ++++---
+ 2 files changed, 9 insertions(+), 12 deletions(-)
+
+commit 47cf9a9633bbff12fef1131e7179dfc351f7e5f3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Dec 8 10:20:25 2018 +0330
+
+    Apply non-controversial parts of ot-style (#1464)
+
+    Things to be used in https://github.com/harfbuzz/harfbuzz/pull/1459
+
+ src/hb-aat-fdsc-table.hh    | 29 +++++++++++++++++++++++++---
+ src/hb-aat-layout-common.hh |  1 +
+ src/hb-ot-head-table.hh     | 13 +++++++++++++
+ src/hb-ot-os2-table.hh      | 46
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-stat-table.hh     | 38 ++++++++++++++++++-------------------
+ 5 files changed, 105 insertions(+), 22 deletions(-)
+
+commit 4d809696ef4db046d11072e5433ea5ff36bd7b26
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Dec 7 20:49:39 2018 -0800
+
+    fix for issue #1447 (#1462)
+
+    Added case for OpCode_BaseFontName. This opcode in spec but
+    practically unused.
+    Added a comment for default case which can't be hit
+
+ src/hb-ot-cff1-table.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 1abd4fcaec31053b442525d7f240af489c5974b1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Dec 7 22:34:12 2018 +0330
+
+    [fdsc] minor
+
+ src/hb-aat-fdsc-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 59345cdef38cf1f514a6a0eb6e8852350acb6166
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Dec 6 13:36:26 2018 -0800
+
+    [CFF] Refix oss-fuzz 11714: set_blends (PR #1458) (#1460)
+
+    * pass subarray of stack to set_blends
+
+    * get_subarray to return a value, not ref
+
+    * restored error check (with tweak)
+
+ src/hb-cff-interp-common.hh |  5 +++++
+ src/hb-cff2-interp-cs.hh    | 14 +++++++++-----
+ 2 files changed, 14 insertions(+), 5 deletions(-)
+
+commit 20245f0000a0f04f2ba172b51ce69ee7ebb256aa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 6 10:27:37 2018 -0800
+
+    Fix likely check
+
+    Ouch!
+
+ src/hb-cff-interp-dict-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit d866e905fd555d393464ed58d5fc11ee453c7ea4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 6 10:26:32 2018 -0800
+
+    Add default value to first argument of sub_array()
+
+ src/hb-dsalgs.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit f1352f7486caaf6d3480ef2ac6b4719acf73e6a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 6 10:21:06 2018 -0800
+
+    Add sub_array to hb_vector_t
+
+ src/hb-vector.hh | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+commit ca23b719357b01e98a5cf533bbf637d6706a4ec2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Dec 6 10:19:03 2018 -0800
+
+    Add default-value for second arg of sub_array()
+
+ src/hb-dsalgs.hh    | 7 +++----
+ src/hb-open-type.hh | 8 ++++----
+ 2 files changed, 7 insertions(+), 8 deletions(-)
+
+commit 6ad3fcddaf2ba8ebc9ad49ff9e7b33b60fcad16a
+Merge: f95324a3 ae087d10
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Dec 6 10:21:00 2018 +0330
+
+    Merge pull request #1458 from harfbuzz/cff-check-blends
+
+    [CFF] oss-fuzz issue 11714: set_blends
+
+commit ae087d10c22249f3aec3239e4eac98a728f71f75
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 21:47:34 2018 -0800
+
+    add minimized test case for oss-fuzz issue 11714
+
+ ...-testcase-minimized-hb-subset-fuzzer-5710107829075968 | Bin 0 ->
+ 3660 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 1ccbdcf73bbc967f5f94c0bc7f7e869bd87d9fa0
+Merge: 14d29a10 f95324a3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 21:37:38 2018 -0800
+
+    Merge branch 'master' into cff-check-blends
+
+commit 14d29a10437205566c4bd7bcfa2282d34d9f4f2f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 21:33:29 2018 -0800
+
+    check number of blends against args on stack
+
+ src/hb-cff2-interp-cs.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit f95324a3351c1f699214ad84d073268218ea83a3
+Merge: 6727c4b6 9d8f3b0d
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Dec 6 08:33:44 2018 +0330
+
+    Merge pull request #1457 from harfbuzz/cff-varstore-sanitize
+
+    [CFF] oss-fuzz issue 11713 (CFF2VariationStore::serialize)
+
+commit 6727c4b6f0356b08803b4d5cde608ec004e3533f
+Merge: d9dabc00 34e3ef8f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 5 17:37:21 2018 -0800
+
+    Merge pull request #1456 from harfbuzz/cff-subr-sanitize
+
+    [CFF] fix oss-fuzz issue 11691 (BlendArg::set_blends)
+
+commit 9d8f3b0dfbf39f5dfa25d52f47e8af6ad318eb17
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 17:14:51 2018 -0800
+
+    add minimized test case for oss-fuzz issue 11713
+
+ ...z-testcase-minimized-hb-subset-fuzzer-5660711141769216 | Bin 0 ->
+ 383 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit c31092ab34641072606f854408eb1bea18ed2507
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 17:04:55 2018 -0800
+
+    sanitize variationStore in CFF2 against its size
+
+ src/hb-ot-cff2-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 34e3ef8ff394f281b8d7e2c08f346a9495692edc
+Merge: 72d8f763 d9dabc00
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 15:50:05 2018 -0800
+
+    Merge branch 'master' into cff-subr-sanitize
+
+commit 72d8f76368b264a42fe58438fe15811d458a7935
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 15:49:11 2018 -0800
+
+    add minimized test case for oss-fuzz issue 11691
+
+ ...z-testcase-minimized-hb-shape-fuzzer-5686369209286656 | Bin 0 ->
+ 2880 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit d9dabc00e9278a346e85538212c126da7e610d55
+Merge: 81cfd3c7 010e2ddb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 5 15:39:34 2018 -0800
+
+    Merge pull request #1454 from harfbuzz/cff-fixbcd
+
+    [CFF] fix oss-fuzz issue 11674: parse_bcd
+
+commit 81cfd3c775dbc470f57d7fe2775cc068ffa367b6
+Merge: 8394a6cb 6708c559
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Dec 5 15:37:15 2018 -0800
+
+    Merge pull request #1455 from harfbuzz/cff-strinc_assert
+
+    [CFF] fix oss-fuzz issue 11675 (ASSERT: count <= str.len)
+
+commit 6dcfda92c17a7701479118751a8290246e9a3c05
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 15:07:46 2018 -0800
+
+    sanitize CFF1 & CFF2 global subrs
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ src/hb-ot-cff2-table.hh | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit 6708c5595fc6babdae0132f8a23cbe3558a58703
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 12:51:18 2018 -0800
+
+    fix oss-fuzz issue 11675 (ASSERT: count <= str.len)
+
+    Also added an additional error check to avail ()
+
+ src/hb-cff-interp-common.hh                           |  18
+ ++++++++++++++++--
+ ...stcase-minimized-hb-subset-fuzzer-5768186323009536 | Bin 0 ->
+ 337 bytes
+ 2 files changed, 16 insertions(+), 2 deletions(-)
+
+commit 010e2ddb384b5a721172fd7466aafec58dbf8063
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 12:23:58 2018 -0800
+
+    minimized test case for oss-fuzz issue 11674
+
+ ...zz-testcase-minimized-hb-subset-fuzzer-5672006905757696 | Bin 0 ->
+ 73 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 2cb9d4c183afc838ecf2ba0d47814e9eaa6f09c6
+Merge: a5fa843c 8394a6cb
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 11:25:29 2018 -0800
+
+    Merge branch 'master' into cff-fixbcd
+
+commit a5fa843c746e20aaca48ece6cff057deb8d916ca
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 11:18:16 2018 -0800
+
+    fixed a bug with fractional part in a negative value
+
+ src/hb-cff-interp-dict-common.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 8394a6cb252dd8b4230c2b59e8c346ec5403bf88
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 5 15:23:41 2018 +0330
+
+    [os2] Make newer table fields accessible (#1452)
+
+ src/hb-ot-os2-table.hh | 88
+ +++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 66 insertions(+), 22 deletions(-)
+
+commit 5ab086ebb18112ef48bf6c913acc91b2009a9bed
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 5 14:17:37 2018 +0330
+
+    [fdsc] Implement the table parsing
+
+    Related to https://github.com/harfbuzz/harfbuzz/issues/1337
+
+    May used in addition to an API related to STAT.
+
+    Lots of Apple fonts have it.
+
+ src/Makefile.sources     |   1 +
+ src/hb-aat-fdsc-table.hh | 103
+ +++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-aat-layout.cc     |   1 +
+ 3 files changed, 105 insertions(+)
+
+commit 8f80e53341a3d5bac6c2c39ab6d6973eedb0b074
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 5 13:51:14 2018 +0330
+
+    [gasp] Implement the table parsing
+
+    May or may not be used in
+    https://github.com/harfbuzz/harfbuzz/pull/1432
+
+ src/Makefile.sources    |  1 +
+ src/hb-ot-gasp-table.hh | 84
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.cc     |  5 +--
+ 3 files changed, 88 insertions(+), 2 deletions(-)
+
+commit 79e7e3445efef2dc57f8a10c7e355e802af08868
+Merge: cf4b7db6 78f639b8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 5 13:25:18 2018 +0330
+
+    Merge pull request #1449 from harfbuzz/cff-fixcharset
+
+    [CFF] fix for oss-fuzz 11657: Charset overrun
+
+commit cf4b7db6b1e01c11d7a8a26d95cf947935a234a7
+Merge: 32cc46c7 803d2f92
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Dec 5 13:23:23 2018 +0330
+
+    Merge pull request #1448 from harfbuzz/cff-leak
+
+    [CFF] fix leak: oss-fuzz 11662
+
+commit 620d1ef588c6ce25644891cfe4b9c20fd8a9d1db
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 00:36:11 2018 -0800
+
+    fix unsigned long const
+
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 28dfb4c14280b05ad0a519f9df2b0eda41a62540
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Dec 5 00:26:03 2018 -0800
+
+    fix signed/unsigned comparison
+
+ src/hb-cff-interp-dict-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f9cee08edd32182044407bf6ffde00df0feb09b7
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 23:58:26 2018 -0800
+
+    use sized int types in parse_bcd
+
+ src/hb-cff-interp-dict-common.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit c01a5f32a33fa875de68ca29a4672fd36a05245b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 23:23:23 2018 -0800
+
+    refix
+
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 755fefc92113e469a1aadee2546958fede156c01
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 23:18:28 2018 -0800
+
+    fix bug
+
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0e81b153aff1f2e301e73ca1a15a9bc5b2e7bb82
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 22:40:07 2018 -0800
+
+    fix typo
+
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 85d4b15cd88ce9a6ffccccf90300f9c184166058
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 22:30:33 2018 -0800
+
+    include float.h
+
+ src/hb-cff-interp-dict-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 5a7c371e4c6f1775ebbfe120fafe92afe402a954
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 22:24:38 2018 -0800
+
+    check overflow & clamp
+
+ src/hb-cff-interp-dict-common.hh | 36
+ +++++++++++++++++++++++++++---------
+ 1 file changed, 27 insertions(+), 9 deletions(-)
+
+commit 32cc46c75a5f163f254b7998ed9193d5bbc85e4b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 21:32:34 2018 -0800
+
+    [CFF] fix oss-fuzz issue 11670: NULL dereference (#1450)
+
+    * guard against no subr access
+
+    * code tweak
+
+    * add minimized testcase for oss-fuzz 11670 (Null deference)
+
+ src/hb-cff-interp-cs-common.hh                     |  22
+ ++++++++++++++++-----
+ src/hb-ot-cff-common.hh                            |   2 +-
+ ...ase-minimized-hb-subset-fuzzer-5672913680728064 | Bin 0 -> 861 bytes
+ 3 files changed, 18 insertions(+), 6 deletions(-)
+
+commit 78f639b8bf508ccfb27224f12442f8e8a1460e08
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 14:17:03 2018 -0800
+
+    added minimized testcase for oss-fuzz issue 11657
+
+ ...zz-testcase-minimized-hb-shape-fuzzer-5700264032468992 | Bin 0 ->
+ 648 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit d3d2f32c6e85de1d7fbbb18afef356e09110e61c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 13:51:26 2018 -0800
+
+    fix oss-fuzz 11657: buffer overrun
+
+    Check overrun in Charset1_2::get_glyph
+
+ src/hb-ot-cff1-table.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit d0a250a7b15f1099c2005bc2427d62e7370dcc33
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Dec 4 23:42:13 2018 +0330
+
+    Reuse hb_aat_layout_has_* logic in coretext-aat detection logic
+    (#1442)
+
+ src/hb-coretext.cc | 16 ++--------------
+ 1 file changed, 2 insertions(+), 14 deletions(-)
+
+commit 803d2f92dca329a84d92c224a73e13906e8b8d56
+Merge: 6ce8d10b c775adc1
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 11:01:26 2018 -0800
+
+    Merge branch 'master' into cff-leak
+
+commit 6ce8d10b45598f5f6dade38e65486f793f33d0b6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 10:39:17 2018 -0800
+
+    add unlikely to error handling
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ src/hb-ot-cff2-table.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit b61f74f69a84f427b40deefefed429fbc915981c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 10:30:35 2018 -0800
+
+    added minimized test case for oss-fuzz issue 11662
+
+ ...testcase-minimized-hb-shape-fuzzer-5175735354916864 | Bin 0 ->
+ 354461 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 0b952e6026c8be13d16d97f464034ee477e6282f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 10:22:35 2018 -0800
+
+    more leak fixes
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ src/hb-ot-cff2-table.hh | 3 ++-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit c775adc1383f72f02b1329628b3eba1dc377a0f7
+Merge: c968869f 04f2ca94
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Dec 4 21:30:07 2018 +0330
+
+    Merge pull request #1444 from harfbuzz/cff-assert
+
+    removed assert, fixes https://github.com/harfbuzz/harfbuzz/issues/1443
+
+commit 9473463f5c884fcb1de8a7ba7410da2601e6ffa8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 09:58:48 2018 -0800
+
+    fix attempt for oss-fuzz 11662 leak
+
+ src/hb-ot-cff1-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 04f2ca94212983d675ed2cd36350be23ff2a6e19
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Dec 4 09:24:07 2018 -0800
+
+    removed assert
+
+ src/hb-ot-cff1-table.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit c968869f212dbfcb86d42fb36049328521cbf00c
+Merge: 8c05b955 c48f53d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Dec 4 04:14:13 2018 -0500
+
+    Merge pull request #1441 from harfbuzz/cff-doublenum
+
+    use double as CFF Number implementation
+
+commit c48f53d30901dfc20b7432c2947e66642010dc4e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Dec 3 16:59:41 2018 -0800
+
+    more double changes
+
+ src/hb-cff2-interp-cs.hh       | 4 ++--
+ test/api/test-ot-extents-cff.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 9424e8052686a6a93e0d30e38aecbe927db9d787
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Dec 3 16:18:10 2018 -0800
+
+    added minimized test cases
+
+ ...zz-testcase-minimized-hb-shape-fuzzer-5647267827023872 | Bin 0 ->
+ 655 bytes
+ ...zz-testcase-minimized-hb-shape-fuzzer-5725855502827520 | Bin 0 ->
+ 655 bytes
+ ...zz-testcase-minimized-hb-shape-fuzzer-5736657639178240 | Bin 0 ->
+ 459 bytes
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 5fff6ab0024547a8ac47723a0047f4b17416d6ce
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Dec 3 16:06:58 2018 -0800
+
+    additional precision made a difference in extents test
+
+ src/hb-cff-interp-common.hh    | 2 +-
+ src/hb-cff2-interp-cs.hh       | 2 +-
+ test/api/test-ot-extents-cff.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 9e5180cd444b6900a0fa0c3df4c8138f9a663383
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Dec 3 15:32:42 2018 -0800
+
+    more double changes
+
+ src/hb-cff-interp-common.hh      |  8 ++++----
+ src/hb-cff-interp-dict-common.hh | 10 +++++-----
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+commit 9af33d7a2ad5ce88fc508bc5c6a56be4650d2621
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Dec 3 14:48:46 2018 -0800
+
+    Number to use double for all types
+
+ src/hb-cff-interp-common.hh | 84
+ +++++++--------------------------------------
+ 1 file changed, 13 insertions(+), 71 deletions(-)
+
+commit 8c05b955eb4aa088b2b5df9b6415863486eaf59c
+Merge: d19b1680 01f628cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 3 14:30:51 2018 -0500
+
+    Merge pull request #1439 from ebraminio/tracking
+
+    [aat] Expose hb_aat_layout_has_tracking API
+
+commit 01f628cf5571b8b58108ab66cfc3e929c9840e31
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Dec 3 22:04:48 2018 +0330
+
+    [aat] Expose hb_aat_layout_has_tracking API
+
+ docs/harfbuzz-sections.txt  |   7 ++++---
+ src/hb-aat-layout.cc        |   9 ++++++++-
+ src/hb-aat-layout.h         |   8 ++++++++
+ src/hb-aat-layout.hh        |   3 ---
+ test/api/fonts/aat-morx.ttf | Bin 0 -> 1620 bytes
+ test/api/fonts/aat-trak.ttf | Bin 0 -> 2456 bytes
+ test/api/test-aat-layout.c  |  13 +++++++++++++
+ 7 files changed, 33 insertions(+), 7 deletions(-)
+
+commit d19b1680b53e54f449736432f369a676c394ebf8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Dec 3 10:41:37 2018 -0500
+
+    [aat] Expose a couple APIs
+
+    New API:
+    +hb_aat_layout_has_substitution()
+    +hb_aat_layout_has_positioning()
+
+ docs/harfbuzz-sections.txt |  2 ++
+ src/hb-aat-layout.cc       | 20 ++++++++++++++++----
+ src/hb-aat-layout.h        | 16 ++++++++++++++++
+ src/hb-aat-layout.hh       |  6 ------
+ 4 files changed, 34 insertions(+), 10 deletions(-)
+
+commit 84efe0438e1cfc5b070e114b70e8c070be6119ca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Dec 2 12:38:53 2018 -0500
+
+    [aat] Fix division sign fallout
+
+    Happened after 11d2f49af8f53340134c844173f4d8655b00dea3
+    since now nClasses is unsigned int...
+
+ src/hb-aat-layout-common.hh                               |   2 +-
+ ...zz-testcase-minimized-hb-shape-fuzzer-5768046065483776 | Bin 0 ->
+ 342 bytes
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 2087f5a2a743380b36399ba8a2b4ff9e93890fcf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 20:04:45 2018 -0500
+
+    Add casts to hb_array_t<>
+
+ src/hb-open-type.hh | 13 ++++++++++---
+ src/hb-vector.hh    |  2 ++
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+commit 58d4d19947794aded4e966290b01e1034f216a7d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 19:34:18 2018 -0500
+
+    Simplify build source list
+
+ CMakeLists.txt       |  12 +--
+ src/Makefile.am      |   6 --
+ src/Makefile.sources | 231
+ ++++++++++++++++++++++++---------------------------
+ 3 files changed, 111 insertions(+), 138 deletions(-)
+
+commit 967a204ee92548163a0d19678a237dcaf3720c20
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 19:28:17 2018 -0500
+
+    Minor
+
+ test/api/hb-subset-test.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 11d2f49af8f53340134c844173f4d8655b00dea3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 13:12:21 2018 -0500
+
+    New approach to change BigEndian casts to be int-sized
+
+    Fixes spurious warnings like:
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1436
+
+ src/hb-open-type.hh | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+commit 50e0273ab18acd2fbb21bcf18ad487092e890b4e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 13:03:52 2018 -0500
+
+    Change hb_assert_unsigned_t<> to hb_is_signed<>
+
+ src/hb-dsalgs.hh | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+commit c3a8b047aab47e40dc107a952b3a1472068ec932
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 00:14:48 2018 -0500
+
+    Revert "Change BigEndian casts to be int-sized"
+
+    This reverts commit eb5ddd32bf4e458ca0af8d5784f8fd46485ad225.
+
+    Broke tests, badly.  To be investigated and reenabled.
+
+ src/hb-open-type.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit be45677ab605efc711a433323d66e4051c289252
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 00:04:29 2018 -0500
+
+    Minor
+
+ src/hb-ot-layout-gsub-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit eb5ddd32bf4e458ca0af8d5784f8fd46485ad225
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Dec 1 00:03:01 2018 -0500
+
+    Change BigEndian casts to be int-sized
+
+    Fixes spurious warnings like:
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1436
+
+ src/hb-open-type.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit e8860fdcaa69e3452edd903f78599bc8fa9d109c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 23:38:24 2018 -0500
+
+    Fix more warning
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit af349ee3487b31c2328f0a37a43d31b248ed14e5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 23:20:50 2018 -0500
+
+    Fix warning
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 825df6dbc7fd013c68d7b5672f81e69b69bc14e7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 23:04:59 2018 -0500
+
+    [CFF] Change spaces to tabs
+
+ src/hb-cff-interp-common.hh      | 389 ++++++++++++++++-----------------
+ src/hb-cff-interp-cs-common.hh   | 324 ++++++++++++++--------------
+ src/hb-cff-interp-dict-common.hh | 190 ++++++++--------
+ src/hb-cff1-interp-cs.hh         |  72 +++----
+ src/hb-cff2-interp-cs.hh         |  76 +++----
+ src/hb-ot-cff-common.hh          | 128 +++++------
+ src/hb-ot-cff1-table.cc          |   4 +-
+ src/hb-ot-cff1-table.hh          | 456
+ +++++++++++++++++++--------------------
+ src/hb-ot-cff2-table.cc          |   4 +-
+ src/hb-ot-cff2-table.hh          | 216 +++++++++----------
+ src/hb-subset-cff-common.cc      |  76 +++----
+ src/hb-subset-cff-common.hh      | 384 ++++++++++++++++-----------------
+ src/hb-subset-cff1.cc            | 416
+ +++++++++++++++++------------------
+ src/hb-subset-cff1.hh            |   2 +-
+ src/hb-subset-cff2.cc            | 240 ++++++++++-----------
+ src/hb-subset-cff2.hh            |   2 +-
+ 16 files changed, 1492 insertions(+), 1487 deletions(-)
+
+commit 592f39b3c4ed04a6f6cf129020358e64782c7108
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 22:54:57 2018 -0500
+
+    [CFF] Whitespace
+
+ src/hb-cff-interp-common.hh      |  7 +++----
+ src/hb-cff-interp-cs-common.hh   |  6 +++---
+ src/hb-cff-interp-dict-common.hh |  6 +++---
+ src/hb-cff2-interp-cs.hh         |  2 +-
+ src/hb-ot-cff-common.hh          | 12 ++++++------
+ src/hb-ot-cff1-table.hh          | 30 +++++++++++++++---------------
+ src/hb-ot-cff2-table.hh          | 12 ++++++------
+ src/hb-subset-cff-common.cc      |  8 ++++----
+ src/hb-subset-cff-common.hh      | 34 +++++++++++++++++-----------------
+ src/hb-subset-cff1.cc            | 20 ++++++++++----------
+ src/hb-subset-cff2.cc            | 18 +++++++++---------
+ 11 files changed, 77 insertions(+), 78 deletions(-)
+
+commit a2e8d1d455c5d0ae22927567cf8a9a2539cd3470
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 22:54:20 2018 -0500
+
+    Minor
+
+ src/Makefile.sources | 27 +++++++++++++--------------
+ 1 file changed, 13 insertions(+), 14 deletions(-)
+
+commit e3dc47c6357813d2dd098aad312d79e9d7c2aa18
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 22:43:22 2018 -0500
+
+    Remove generated files that were accidentally added by CFF2 branch
+
+ gtk-doc.make      |  320 --
+ m4/libtool.m4     | 8369
+ -----------------------------------------------------
+ m4/ltoptions.m4   |  437 ---
+ m4/ltsugar.m4     |  124 -
+ m4/ltversion.m4   |   23 -
+ m4/lt~obsolete.m4 |   99 -
+ 6 files changed, 9372 deletions(-)
+
+commit 5e64e0f53259dbc0a3ea8e220ded15e85bbc1782
+Merge: 09096aa8 d8c69137
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 22:40:54 2018 -0500
+
+    Merge pull request #1113 from harfbuzz/cff-subset
+
+    CFF/CFF2 subsetter
+
+commit 09096aa89f1944dff94a5518bce578eba8989e74
+Author: Bruce Mitchener <bruce.mitchener@gmail.com>
+Date:   Sat Dec 1 10:22:49 2018 +0700
+
+    Use nullptr instead of 0/NULL. (#1435)
+
+    * Use nullptr instead of 0/NULL.
+
+    * Update test-name-table.cc
+
+ src/hb-debug.hh        | 2 +-
+ src/test-name-table.cc | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit d8c69137655fbe9678d1dfef0eb3c4172f8bbfc0
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 18:58:14 2018 -0800
+
+    undo 0u
+
+ src/hb-cff2-interp-cs.hh    | 2 +-
+ src/hb-ot-cff1-table.hh     | 4 ++--
+ src/hb-ot-vorg-table.hh     | 2 +-
+ src/hb-subset-cff-common.hh | 4 ++--
+ src/hb-subset-cff1.cc       | 4 ++--
+ 5 files changed, 8 insertions(+), 8 deletions(-)
+
+commit 2c859b3880868b30823eb00bed90dc0de873628b
+Merge: 9483da14 bb72de66
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 18:47:34 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit bb72de66ddf3ae9ae53cf68642cb228e88aa64f5
+Merge: fedd8e6c fb059082
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 21:36:35 2018 -0500
+
+    Merge pull request #1433 from harfbuzz/overload-overload
+
+    Fix ambiguous overload errors with old compilers
+
+commit fb059082138bf17a5a8616410d9a35f927f9fd85
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 20:45:40 2018 -0500
+
+    Revert ugly fixes
+
+    Now that we have 6daf45e0, revert cryptic hacks...
+
+    This reverts commit abd81ed4f5cbc5a94171747909bc6b77551cb929.
+    This reverts commit 9c6921c08c905a0cf45ba0182134e6ff910fac51.
+    This reverts commit d39760cabfe4007cefdfc45231e85e93fababac2.
+    This reverts commit fedd8e6c176dea85194693399e50243eb1c117c4.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1374
+
+ src/hb-aat-layout-morx-table.hh |  4 ++--
+ src/hb-face.cc                  |  4 ++--
+ src/hb-machinery.hh             |  4 ++--
+ src/hb-ot-color-cpal-table.hh   |  2 +-
+ src/hb-ot-kern-table.hh         |  2 +-
+ src/hb-ot-layout-gpos-table.hh  | 32 ++++++++++++++++----------------
+ src/hb-ot-layout-gsubgpos.hh    | 14 +++++++-------
+ 7 files changed, 31 insertions(+), 31 deletions(-)
+
+commit dfad19ad5aefdacecca6af81917abc2670d4416f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 19:57:12 2018 -0500
+
+    Make operator [] take signed int
+
+    The built-in operator takes signed int.  So, match it, such that
+    the built-in is never a better or equally-good match to our operator.
+    Fixes "ambiguous overload" errors from gcc 4.2 and VS 2008.
+
+    See https://github.com/harfbuzz/harfbuzz/issues/1374
+
+ src/hb-dsalgs.hh    |  3 ++-
+ src/hb-open-type.hh | 42 ++++++++++++++++++++++++++++--------------
+ src/hb-vector.hh    |  6 ++++--
+ 3 files changed, 34 insertions(+), 17 deletions(-)
+
+commit 9483da145d6da1bdfa3224fe13a5b4e9b449d19f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 16:59:41 2018 -0800
+
+    redo fixes
+
+ src/hb-cff2-interp-cs.hh    | 2 +-
+ src/hb-ot-cff1-table.hh     | 4 ++--
+ src/hb-subset-cff-common.hh | 6 +++---
+ src/hb-subset-cff1.cc       | 4 ++--
+ 4 files changed, 8 insertions(+), 8 deletions(-)
+
+commit 291da448237cdc0b5534fbc1ce2288e1aa8e7b8a
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 16:50:46 2018 -0800
+
+    yet another
+
+ src/hb-subset-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b1821b9d092e4fd7fd888f4bffc341283bace461
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 16:31:01 2018 -0800
+
+    some more
+
+ src/hb-subset-cff-common.hh | 4 ++--
+ src/hb-subset-cff1.cc       | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 9784cff55688d1ee93275e39c2339d5a486ed78b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 16:07:08 2018 -0800
+
+    fix another pesky gcc error
+
+ src/hb-cff2-interp-cs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 23a797b44365ed76fc7db25be13bd9c3580a8695
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 15:15:31 2018 -0800
+
+    silence picky gcc errors
+
+ src/hb-ot-cff1-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9ae954f43ad1eb703d54db98ce46157370b71a9c
+Merge: 471db3aa fedd8e6c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 30 15:00:52 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit fedd8e6c176dea85194693399e50243eb1c117c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 16:50:30 2018 -0500
+
+    One more.........
+
+    I wonder if there's something better to do about these :(.
+
+    In file included from hb-ot-color.cc:31:
+    hb-ot-color-cpal-table.hh: In member function 'unsigned int
+    OT::CPAL::get_size() const':
+    hb-ot-color-cpal-table.hh:118: error: ISO C++ says that these are
+    ambiguous, even though the worst conversion for the first is better
+    than the worst conversion for the second:
+
+ src/hb-ot-color-cpal-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bc5db9b0807767ac04d6e50070d69cb9c520f06e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 16:04:52 2018 -0500
+
+    One more....
+
+    hb-ot-vorg-table.hh:96: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-vector.hh:87: note: candidate 1: const Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) const [with Type =
+    OT::VertOriginMetric, unsigned int PreallocedCount = 8u]
+    hb-ot-vorg-table.hh:96: note: candidate 2: operator[](const T*,
+    int) <built-in>
+
+ src/hb-ot-vorg-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d39760cabfe4007cefdfc45231e85e93fababac2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 15:55:30 2018 -0500
+
+    One more...
+
+    Sigh.
+
+    hb-ot-kern-table.hh: In member function 'int
+    OT::KernSubTableFormat3<KernSubTableHeader>::get_kerning(hb_codepoint_t,
+    hb_codepoint_t) const':
+    hb-ot-kern-table.hh:59: error: ambiguous overload for 'operator[]'
+    in 'kernValue[kernIndex[i]]'
+    hb-ot-kern-table.hh:59: note: candidates are: operator[](T*, int)
+    <built-in>
+    hb-dsalgs.hh:574: note:                 Type&
+    hb_array_t<Type>::operator[](unsigned int) const [with Type = const
+    OT::IntType<short int, 2u>]
+
+ src/hb-ot-kern-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9c6921c08c905a0cf45ba0182134e6ff910fac51
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 15:16:57 2018 -0500
+
+    More...
+
+    hb-ot-layout-gsubgpos.hh:1707: error: ISO C++ says that these are
+    ambiguous, even though the worst conversion for the first is better
+    than the worst conversion for the second:
+    ...
+
+ src/hb-aat-layout-morx-table.hh |  4 ++--
+ src/hb-ot-layout-gpos-table.hh  | 32 ++++++++++++++++----------------
+ src/hb-ot-layout-gsubgpos.hh    | 16 ++++++++--------
+ 3 files changed, 26 insertions(+), 26 deletions(-)
+
+commit f998bb2086342d6fdcd4295593eddea91396e0b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 12:52:21 2018 -0500
+
+    More weird fixes
+
+    In file included from hb-ot-name.cc:29:
+    hb-ot-name-table.hh: In member function 'unsigned int
+    OT::name::get_size() const':
+    hb-ot-name-table.hh:157: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-open-type.hh:354: note: candidate 1: const Type&
+    OT::UnsizedArrayOf<Type>::operator[](unsigned int) const [with Type
+    = OT::NameRecord]
+    hb-ot-name-table.hh:157: note: candidate 2: operator[](const T*,
+    int) <built-in>
+    hb-ot-name-table.hh: In member function 'void
+    OT::name::accelerator_t::init(hb_face_t*)':
+    hb-ot-name-table.hh:196: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-dsalgs.hh:574: note: candidate 1: Type&
+    hb_array_t<Type>::operator[](unsigned int) const [with Type =
+    const OT::NameRecord]
+    hb-ot-name-table.hh:196: note: candidate 2: operator[](T*, int)
+    <built-in>
+    hb-ot-name-table.hh:197: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-dsalgs.hh:574: note: candidate 1: Type&
+    hb_array_t<Type>::operator[](unsigned int) const [with Type =
+    const OT::NameRecord]
+    hb-ot-name-table.hh:197: note: candidate 2: operator[](T*, int)
+    <built-in>
+    hb-ot-name-table.hh:198: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-dsalgs.hh:574: note: candidate 1: Type&
+    hb_array_t<Type>::operator[](unsigned int) const [with Type =
+    const OT::NameRecord]
+    hb-ot-name-table.hh:198: note: candidate 2: operator[](T*, int)
+    <built-in>
+    make[4]: *** [libharfbuzz_la-hb-ot-name.lo] Error 1
+    make[3]: *** [all-recursive] Error 1
+
+ src/hb-ot-name-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 67fd94da98f950b5feb719ac805f2a45379fc935
+Merge: abd81ed4 ae79fdaa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 11:53:30 2018 -0500
+
+    Merge commit 'ae79fdaa7774d3f886a8f03926577c3bd2010b03'
+
+commit abd81ed4f5cbc5a94171747909bc6b77551cb929
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 11:51:26 2018 -0500
+
+    Umm.  Cryptic, yes
+
+    In file included from hb-face.cc:35:
+    hb-ot-cmap-table.hh: In member function 'void
+    OT::CmapSubtableFormat4::_compiles_assertion_on_line_388() const':
+    hb-ot-cmap-table.hh:388: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-open-type.hh:354: note: candidate 1: const Type&
+    OT::UnsizedArrayOf<Type>::operator[](unsigned int) const [with Type =
+    OT::IntType<short unsigned int, 2u>]
+    hb-ot-cmap-table.hh:388: note: candidate 2: operator[](const T*,
+    int) <built-in>
+    hb-ot-cmap-table.hh: In member function 'void
+    OT::CmapSubtableFormat4::_instance_assertion_on_line_388() const':
+    hb-ot-cmap-table.hh:388: error: ISO C++ says that these are ambiguous,
+    even though the worst conversion for the first is better than the
+    worst conversion for the second:
+    hb-open-type.hh:354: note: candidate 1: const Type&
+    OT::UnsizedArrayOf<Type>::operator[](unsigned int) const [with Type =
+    OT::IntType<short unsigned int, 2u>]
+    hb-ot-cmap-table.hh:388: note: candidate 2: operator[](const T*,
+    int) <built-in>
+    hb-face.cc: In function 'hb_blob_t*
+    _hb_face_builder_data_reference_blob(hb_face_builder_data_t*)':
+    hb-face.cc:650: error: ISO C++ says that these are ambiguous, even
+    though the worst conversion for the first is better than the worst
+    conversion for the second:
+    hb-vector.hh:81: note: candidate 1: Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) [with Type =
+    hb_face_builder_data_t::table_entry_t, unsigned int PreallocedCount
+    = 32u]
+    hb-face.cc:650: note: candidate 2: operator[](T*, int) <built-in>
+    hb-face.cc:650: error: ISO C++ says that these are ambiguous, even
+    though the worst conversion for the first is better than the worst
+    conversion for the second:
+    hb-vector.hh:81: note: candidate 1: Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) [with Type =
+    hb_face_builder_data_t::table_entry_t, unsigned int PreallocedCount
+    = 32u]
+    hb-face.cc:650: note: candidate 2: operator[](const T*, int)
+    <built-in>
+    hb-face.cc:651: error: ISO C++ says that these are ambiguous, even
+    though the worst conversion for the first is better than the worst
+    conversion for the second:
+    hb-vector.hh:81: note: candidate 1: Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) [with Type =
+    hb_face_builder_data_t::table_entry_t, unsigned int PreallocedCount
+    = 32u]
+    hb-face.cc:651: note: candidate 2: operator[](T*, int) <built-in>
+    hb-face.cc:651: error: ISO C++ says that these are ambiguous, even
+    though the worst conversion for the first is better than the worst
+    conversion for the second:
+    hb-vector.hh:81: note: candidate 1: Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) [with Type =
+    hb_face_builder_data_t::table_entry_t, unsigned int PreallocedCount
+    = 32u]
+    hb-face.cc:651: note: candidate 2: operator[](const T*, int)
+    <built-in>
+
+ src/hb-face.cc      | 4 ++--
+ src/hb-machinery.hh | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit ae79fdaa7774d3f886a8f03926577c3bd2010b03
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 11:51:26 2018 -0500
+
+    Umm.  Cryptic, yes
+
+    hb-face.cc:650: error: ISO C++ says that these are ambiguous, even
+    though the worst conversion for the first is better than the worst
+    conversion for the second:
+    hb-vector.hh:81: note: candidate 1: Type& hb_vector_t<Type,
+    PreallocedCount>::operator[](unsigned int) [with Type =
+    hb_face_builder_data_t::table_entry_t, unsigned int PreallocedCount
+    = 32u]
+    hb-face.cc:650: note: candidate 2: operator[](T*, int) <built-in>
+
+ src/hb-face.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0f32c95e1487ffcc37439635c3294f941eae857a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 11:31:39 2018 -0500
+
+    Fix a few more sizeof(vector[0]) errors with weird compilers
+
+ src/hb-face.cc | 4 ++--
+ src/hb-set.hh  | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 88630a458b21b811075bed9e761a94c50736dc11
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 01:11:04 2018 -0500
+
+    Fix build for realz
+
+ src/hb-ot-deprecated.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 346286d04eb616c43ba8c796211fa2e5e7bf1983
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 00:44:40 2018 -0500
+
+    Fix build
+
+ src/hb-ot-deprecated.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 31f39cb41e1497a76c5838c93f9b4034089049f2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 00:38:08 2018 -0500
+
+    [post] Rename v2 to v2X
+
+ src/hb-ot-post-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit e3dd47e6025a7f082af4830ba483d90d9b44381f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 30 00:32:12 2018 -0500
+
+    Move things
+
+ src/Makefile.sources   |   1 +
+ src/hb-deprecated.h    |  61 +---------------------------
+ src/hb-ot-deprecated.h | 106
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot.h            |   1 +
+ 4 files changed, 109 insertions(+), 60 deletions(-)
+
+commit 27a6b0a2f7255ed6fc7bfe1f10052c2e344e319b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 16:29:30 2018 -0500
+
+    Fix build for realz
+
+ src/hb-coretext.cc  |  2 +-
+ src/hb-uniscribe.cc | 10 +++++-----
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit e2af4dd1ecbe398c60fe5f3f370dd35400d7e1eb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 16:03:15 2018 -0500
+
+    [uniscribe] Fix build
+
+ src/hb-uniscribe.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bf738ba3ba80778c7feb95ece446607a250d9382
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 30 00:06:40 2018 +0330
+
+    [test][aat] Remove extra --shaper ot
+
+    As run-tests.py already adds it
+
+ test/shaping/data/in-house/tests/macos.tests | 64
+ ++++++++++++++--------------
+ 1 file changed, 32 insertions(+), 32 deletions(-)
+
+commit b65645bbafb3f1f9f956df3028cf4479a4bdc265
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 29 23:57:50 2018 +0330
+
+    [ci] Re-enable llvm-gcc-4.2 bots (#1429)
+
+ .circleci/config.yml | 48
+ ++++++++++++++++++++++++------------------------
+ 1 file changed, 24 insertions(+), 24 deletions(-)
+
+commit e7bd29ea11bd6301a332b471120a4a2cd8575d09
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 29 23:47:20 2018 +0330
+
+    Limit __builtin_bswap16 to GCC >= 5 as it was implemented on 4.8
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ac0264717b949df8840b179d882a9bed2993fb74
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 15:07:44 2018 -0500
+
+    [coretext] Fix compile
+
+    Fingers crossed.
+
+ src/hb-coretext.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5c4fead734b082e0168e6811bec4bcaa19acc36a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 15:04:34 2018 -0500
+
+    Convert "static const hb_tag_t" constants to enum
+
+ src/hb-aat-layout-ankr-table.hh |  2 +-
+ src/hb-aat-layout-bsln-table.hh |  2 +-
+ src/hb-aat-layout-feat-table.hh |  2 +-
+ src/hb-aat-layout-just-table.hh |  2 +-
+ src/hb-aat-layout-kerx-table.hh |  2 +-
+ src/hb-aat-layout-lcar-table.hh |  2 +-
+ src/hb-aat-layout-morx-table.hh |  6 +++---
+ src/hb-aat-layout-trak-table.hh |  2 +-
+ src/hb-aat-ltag-table.hh        |  2 +-
+ src/hb-ot-cmap-table.hh         |  2 +-
+ src/hb-ot-color-cbdt-table.hh   |  4 ++--
+ src/hb-ot-color-colr-table.hh   |  2 +-
+ src/hb-ot-color-cpal-table.hh   |  2 +-
+ src/hb-ot-color-sbix-table.hh   |  2 +-
+ src/hb-ot-color-svg-table.hh    |  2 +-
+ src/hb-ot-glyf-table.hh         |  4 ++--
+ src/hb-ot-hdmx-table.hh         |  2 +-
+ src/hb-ot-head-table.hh         |  2 +-
+ src/hb-ot-hhea-table.hh         |  4 ++--
+ src/hb-ot-hmtx-table.hh         | 14 +++++++-------
+ src/hb-ot-kern-table.hh         |  6 +++---
+ src/hb-ot-layout-base-table.hh  |  2 +-
+ src/hb-ot-layout-gdef-table.hh  |  2 +-
+ src/hb-ot-layout-gpos-table.hh  |  2 +-
+ src/hb-ot-layout-gsub-table.hh  |  2 +-
+ src/hb-ot-layout-jstf-table.hh  |  2 +-
+ src/hb-ot-math-table.hh         |  2 +-
+ src/hb-ot-maxp-table.hh         |  2 +-
+ src/hb-ot-name-table.hh         |  2 +-
+ src/hb-ot-os2-table.hh          |  2 +-
+ src/hb-ot-post-table.hh         |  2 +-
+ src/hb-ot-stat-table.hh         |  2 +-
+ src/hb-ot-var-avar-table.hh     |  2 +-
+ src/hb-ot-var-fvar-table.hh     |  2 +-
+ src/hb-ot-var-hvar-table.hh     |  8 ++++----
+ src/hb-ot-var-mvar-table.hh     |  2 +-
+ src/hb-ot-vorg-table.hh         |  2 +-
+ 37 files changed, 53 insertions(+), 53 deletions(-)
+
+commit 9e4138c82548c2b29a1ae8801d2c6c7c1f1a9c7a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 15:01:10 2018 -0500
+
+    Convert misc "static const" constants to enum
+
+ src/hb-aat-layout-kerx-table.hh |  4 ++--
+ src/hb-map.hh                   |  2 +-
+ src/hb-ot-kern-table.hh         |  4 ++--
+ src/hb-set-digest.hh            | 14 +++++++-------
+ 4 files changed, 12 insertions(+), 12 deletions(-)
+
+commit 44cbd2ea3dc36312bd80860983b6616586e78c6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 14:53:43 2018 -0500
+
+    Convert "static const bool" constants to anonymous enum
+
+ src/hb-aat-layout-common.hh     |  4 ++--
+ src/hb-aat-layout-kerx-table.hh |  4 ++--
+ src/hb-aat-layout-morx-table.hh |  8 ++++----
+ src/hb-dsalgs.hh                | 16 ++++++++--------
+ src/hb-ot-kern-table.hh         |  4 ++--
+ src/hb-ot-layout.cc             |  4 ++--
+ 6 files changed, 20 insertions(+), 20 deletions(-)
+
+commit 861bc75349257f74c12b261abfcd5ab9e2f04863
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 14:34:44 2018 -0500
+
+    [vector] Make pointer cast explicit
+
+    Too bad this doesn't help MSVC 2008 build, as explicit operators are
+    C++11.
+
+ src/hb-machinery.hh     | 2 +-
+ src/hb-ot-cmap-table.hh | 3 ++-
+ src/hb-set.hh           | 4 ++--
+ src/hb-subset.cc        | 2 +-
+ src/hb-vector.hh        | 4 ++--
+ 5 files changed, 8 insertions(+), 7 deletions(-)
+
+commit 72955e68256806f082439d65e6f9b5cf2e35fa8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 14:28:44 2018 -0500
+
+    Hand-hold older compilers
+
+ src/hb-set.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1a182e97ee71de0e78a70ff823ae17fa93a31830
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 12:39:52 2018 -0500
+
+    [test/text-rendering-tests] Update from upstream
+
+ .../text-rendering-tests/fonts/TestGVAR-Composite-0.ttf  | Bin 0 ->
+ 3136 bytes
+ .../fonts/TestGVAR-Composite-Missing.ttf                 | Bin 0 ->
+ 2984 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 000d4b128eba58677acdc3b361829ff2f9a257b1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 12:32:47 2018 -0500
+
+    Make shaper's override_features() override user features as well
+
+    The override_features is used to override features that are normally
+    discretionary features, but in a specific shaper are for various
+    reasons desired to be bolted on or off, because they've been used
+    for inherent shaping.  As such, it makes sense that they also
+    override user features.  Ie. if user turned 'liga' on, we don't
+    want Khmer shaping to become broken...  Or turn 'clig' off...
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1310
+
+ src/hb-ot-shape.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit a95d9d8c8465ebc927bc2194dffe4ea95542e54c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 12:30:14 2018 -0500
+
+    [khmer] Move 'clig' to overrides
+
+    Prerequisite for https://github.com/harfbuzz/harfbuzz/issues/1310
+
+ src/hb-ot-shape-complex-khmer.cc | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+commit 282ce7230b8bd8ad65c408cdaf1499504038247d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 12:18:14 2018 -0500
+
+    Fix "typename outside template" issues
+
+    Nothing an extra template class wouldn't fix...
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1419
+
+ src/hb-null.hh | 25 +++++++++++++++++++------
+ 1 file changed, 19 insertions(+), 6 deletions(-)
+
+commit dc41ecef85b094b30c612113606597b91c55351c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 11:53:53 2018 -0500
+
+    2.2.0
+
+ NEWS                 | 35 +++++++++++++++++++++++++++++++++++
+ configure.ac         |  2 +-
+ src/hb-aat-layout.cc |  6 +++---
+ src/hb-aat-layout.h  |  4 ++--
+ src/hb-deprecated.h  |  4 ++--
+ src/hb-ot-var.cc     |  8 ++++----
+ src/hb-ot-var.h      |  4 ++--
+ src/hb-version.h     |  6 +++---
+ 8 files changed, 52 insertions(+), 17 deletions(-)
+
+commit 7b85081be4fbd6cad75dc28ae933ce920f71b22d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 11:34:22 2018 -0500
+
+    [icu] Minor
+
+ src/hb-icu.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0bcb1de1265368a27e53c6d935c965cbcb4130a0
+Merge: e0307de8 a85886fc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 29 10:39:18 2018 -0500
+
+    Merge pull request #1418 from gvictor/replace_icu_deprecated
+
+    Replace @Deprecated ICU API - USCRIPT_CODE_LIMIT
+
+commit e0307de818ad1f70ef96938642bda61d7a62532a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 29 11:36:05 2018 +0330
+
+    [test][aat.kern] More (#1427)
+
+ test/shaping/data/in-house/tests/macos.tests | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+commit 471db3aa6f963ecd4ebaf66daa81ef245d30d3b8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 28 17:06:11 2018 -0800
+
+    workaround for issue #1417
+
+ src/hb-cff-interp-common.hh | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 32d291ae899eb095500052bed2a22e5255a34838
+Merge: 1ecbf4d3 949655aa
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 28 16:27:45 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit 949655aa7853a4513af6b5247b9822be38f5d322
+Merge: 7b78d223 d3d0f15f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 17:21:57 2018 -0500
+
+    Merge pull request #1425 from mbutterick/patch-1
+
+    update simple shaping example (closes #298)
+
+commit d3d0f15f7d20bedf7018fb2fb652f92ff4159bd7
+Author: Matthew Butterick <mbutterick@users.noreply.github.com>
+Date:   Wed Nov 28 13:46:12 2018 -0800
+
+    update simple shaping example (closes #298)
+
+    add call to `FT_Set_Char_Size`, otherwise default size remains at
+    `0`, and glyph positions come back as `0` too
+
+ docs/usermanual-getting-started.xml | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7b78d2233df0e51e2967bc54a9202b3f9e05059a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 29 00:55:05 2018 +0330
+
+    [test][aat] Update expectency
+
+    It is not visually noticeable but apparently affected by kern format2
+    correct implementation.
+    I should've checked CoreText result which can't as CircleCI outage.
+
+ test/shaping/data/in-house/tests/macos.tests | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 5155067e10011f78f1ce35b3dadb062bccd3a706
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 29 00:07:00 2018 +0330
+
+    [test] Add test for format2 kern (#1423)
+
+ test/shaping/data/in-house/Makefile.sources             |   1 +
+ .../fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf  | Bin 0 ->
+ 34116 bytes
+ test/shaping/data/in-house/tests/kern-format2.tests     |   3 +++
+ 3 files changed, 4 insertions(+)
+
+commit 42a2b496e428521151ff5cb07454d2e993f892cc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 15:24:30 2018 -0500
+
+    [kerx] Fix Format2 index calc again
+
+ src/hb-aat-layout-common.hh     | 14 ++++++++++++++
+ src/hb-aat-layout-kerx-table.hh |  2 +-
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+commit 9e4f03b6ed80a81f8aee5ba93564f5eabab4299c
+Merge: 19863c80 a3267cf8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 15:08:01 2018 -0500
+
+    Merge remote-tracking branch 'fdo/master'
+
+commit a3267cf803082af157a7f2b0026af2633b14f8e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 15:06:01 2018 -0500
+
+    [kern] Fix kern table Format2 offsetToIndex
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1421
+
+ src/hb-aat-layout-kerx-table.hh | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit f9a9c0fd1e561715d696c7bd840bab552d0718ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 14:51:56 2018 -0500
+
+    [kerx] Fix ClassTable implementation for 'kern' table Format 2
+
+ src/hb-aat-layout-common.hh     |  8 +++++---
+ src/hb-aat-layout-kerx-table.hh | 10 ++--------
+ 2 files changed, 7 insertions(+), 11 deletions(-)
+
+commit 5b4a789ca857664668ff69936574dcd09bee6065
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 28 14:46:26 2018 -0500
+
+    [aat] Towards adding two ClassTable's
+
+ src/hb-aat-layout-common.hh | 40 ++++++++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 20 deletions(-)
+
+commit 19863c805982d5d1d059d4dd9376039d3fdaabcd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Nov 28 20:28:42 2018 +0330
+
+    [test][aat] Add a test and make macOS runners faster (#1422)
+
+ .circleci/config.yml                         | 15 +++-----
+ test/shaping/data/in-house/tests/macos.tests | 54
+ ++++++++++++++--------------
+ 2 files changed, 33 insertions(+), 36 deletions(-)
+
+commit 987f4187722a05e3f360b85c66309a351fc5d6ad
+Merge: 1042d9fb 4e2a03b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 27 17:40:32 2018 -0500
+
+    Merge pull request #1398 from Adenilson/bigInt01
+
+    Optimize harfbuzz big integer conversions
+
+commit 4e2a03b6b6e0c0d1c4edea10dc1aae63eeb6c581
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 27 17:40:09 2018 -0500
+
+    Comment
+
+ src/hb-machinery.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 4a719a7f4c997ea7e47588bc0288c97706dae015
+Author: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
+Date:   Tue Nov 20 14:41:19 2018 -0800
+
+    Optimize harfbuzz big integer conversions
+
+    Profiling showed that type conversions were adding considerable
+    cycles in time
+    spent doing text shaping.
+
+    The idea is to optimize it using native processor instructions to
+    help Blink
+    layout performance.
+
+    Doing further investigation revelead that compilers may not use the
+    proper instruction on ARM 32bits builds (i.e. REV16).
+
+    One way to insure that the generated ASM was ideal for both gcc/clang
+    was using __builtin_bswap16.
+
+    Added bonus is that we no longer need to test for CPU architecture.
+
+ src/hb-machinery.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit a85886fc77083084e9a12ee15b47eab7876f9f53
+Author: Victor Chang <vichang@google.com>
+Date:   Tue Nov 27 11:34:56 2018 +0000
+
+    Replace @Deprecated ICU API - USCRIPT_CODE_LIMIT
+
+    Use of the deprecated API USCRIPT_CODE_LIMIT prevents harfbuzz
+    using the ICU4C as a shared library.
+
+    The API has been replaced by u_getIntPropertyMaxValue(UCHAR_SCRIPT)
+
+ src/hb-icu.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 1042d9fbc05aff9d51f15c2824a8521e963d0acd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Nov 26 18:58:39 2018 +0330
+
+    [ci] Add .codecov.yml
+
+    Similar to
+    https://github.com/GoogleChrome/lighthouse/blob/master/.codecov.yml
+
+    No strong preference on commenting, feel free to enable it again
+
+ .codecov.yml | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+commit 97eaedca5de76c74534bab41562aee130098558a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Nov 26 16:58:58 2018 +0330
+
+    [test][aat] Enable Tamil MN test (#1414)
+
+ test/shaping/data/in-house/tests/macos.tests | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 574d888c8a409295a952361a39c8e83a52a0fc3d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 16:51:22 2018 -0500
+
+    [aat] Ignore GSUB table of Muthu Foundry if they have morx table
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1410
+
+ src/hb-ot-layout-gpos-table.hh |  3 +++
+ src/hb-ot-layout-gsub-table.hh |  3 +++
+ src/hb-ot-layout-gsubgpos.hh   |  5 +++++
+ src/hb-ot-layout.cc            | 36 +++++++++++++++++++++++++++++++++++-
+ 4 files changed, 46 insertions(+), 1 deletion(-)
+
+commit 4151c2848d8df75b6d0a4f5d79bee843158aa4a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 16:38:36 2018 -0500
+
+    [GDEF] Move more code
+
+ src/hb-ot-layout-gdef-table.hh | 10 +++++++++-
+ src/hb-ot-layout.cc            | 11 -----------
+ 2 files changed, 9 insertions(+), 12 deletions(-)
+
+commit 4f21703f225b6977196ef180e8d7300ea86d2cc3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 15:59:18 2018 -0500
+
+    [GDEF] Move code around
+
+ src/hb-ot-layout-gdef-table.hh |  3 +++
+ src/hb-ot-layout.cc            | 16 +++++++---------
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+commit 4ed9fb1a0050f3151f9332f08c8bb2c13652c607
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 15:51:01 2018 -0500
+
+    [GDEF] Minor
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0e3a48e54248d69197e8fb23c824d987f91b3bf7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 13:37:23 2018 +0330
+
+    [test][aat] fix 10.13.6 Helvetica expectation
+
+ test/shaping/data/in-house/tests/macos.tests | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit cbc541b426f01717641f1f3529a7c9703aec7a28
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 12:50:30 2018 +0330
+
+    [aat] Add m grave test (#1412)
+
+ test/shaping/data/in-house/tests/macos.tests | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit fa26ad0f48462063f2160a43cb62b018bb21e251
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 11:25:17 2018 +0330
+
+    [aat] Fix macos expectation
+
+ test/shaping/data/in-house/tests/macos.tests | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 926f512f354835f8323bb2c2e58789dd918a9b65
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 01:14:40 2018 -0500
+
+    [aat.feat] Rework API and implementation
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1346
+
+ docs/harfbuzz-docs.xml          |  5 +++
+ docs/harfbuzz-sections.txt      |  7 ++--
+ src/hb-aat-layout-feat-table.hh | 89
+ +++++++++++++++++++++++------------------
+ src/hb-aat-layout.cc            | 80 ++++++++++++++++--------------------
+ src/hb-aat-layout.h             | 32 +++++++++------
+ test/api/test-aat-layout.c      | 58 ++++++++++++++-------------
+ 6 files changed, 141 insertions(+), 130 deletions(-)
+
+commit 84dacbca7ea54a3ca2d5d711d50272a7f3baf456
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 12:08:36 2018 -0500
+
+    [aat.feat] Add _MAX_VALUE to enums
+
+ src/hb-aat-layout.h | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 3922aae1620958768d3257c0988432d5609dca1b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 11:02:04 2018 -0500
+
+    [aat.feat] Minor
+
+ src/hb-aat-layout-feat-table.hh | 12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+commit 0f8e98eca2463da3b83d1b66a19259a584df1682
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 11:00:42 2018 -0500
+
+    [aat.feat] Whitespace
+
+ src/hb-aat-layout-feat-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit c2256068339c9e10c8e6df5d1749be4b4eb04ad4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:54:40 2018 -0500
+
+    [aat.feat] Port to SortedUnsizedArrayOf.bsearch()
+
+ src/hb-aat-layout-feat-table.hh | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+commit 52ae9867efd6520d17306b9f3ad612fe5463e93d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:46:56 2018 -0500
+
+    [AAT.feat] Use lsearch for looking up SettingName's
+
+    They are not sorted.
+
+ src/hb-aat-layout-feat-table.hh | 18 ++++++------------
+ src/hb-open-type.hh             | 16 ++++++++--------
+ src/hb-static.cc                |  6 ++++--
+ 3 files changed, 18 insertions(+), 22 deletions(-)
+
+commit 44b9331f663c09174d94e06baf36d48a50599c42
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:30:35 2018 -0500
+
+    [aat] Fix include issues
+
+ src/Makefile.am | 2 ++
+ src/hb-aat.h    | 2 ++
+ 2 files changed, 4 insertions(+)
+
+commit b206133d1f616339a57996b634dadc7f0a2c4cfb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 14:05:11 2018 -0500
+
+    [aat] Move contents of hb-aat.h to hb-aat-layout.h
+
+    Since it was pages and pages...
+
+ src/Makefile.sources |   1 +
+ src/hb-aat-layout.cc |   1 -
+ src/hb-aat-layout.h  | 452
+ +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-aat-layout.hh |   1 -
+ src/hb-aat-map.hh    |   1 -
+ src/hb-aat.h         | 417
+ +----------------------------------------------
+ src/hb.hh            |   2 +
+ 7 files changed, 458 insertions(+), 417 deletions(-)
+
+commit 2cb235d0210e74ea4ee123767b489301a9c340ab
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 12:23:35 2018 -0500
+
+    [aat.feat] Fix enum namespace
+
+ src/hb-aat-layout-feat-table.hh |   2 +-
+ src/hb-aat-layout-morx-table.hh |   4 +-
+ src/hb-aat-layout.cc            | 150 ++++++------
+ src/hb-aat.h                    | 502
+ ++++++++++++++++++++--------------------
+ test/api/test-aat-layout.c      |   2 +-
+ 5 files changed, 330 insertions(+), 330 deletions(-)
+
+commit 712762cabbbe85e6ab8361cd115c22a176827734
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 12:21:02 2018 -0500
+
+    Minor
+
+ src/hb-aat.h | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit e20f81f4fa977a8d22c6afee1e46fbf46bc182d9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 11:57:42 2018 -0500
+
+    [aat] Rename feat API a bit more
+
+ docs/harfbuzz-sections.txt      | 10 +++++-----
+ src/hb-aat-layout-feat-table.hh |  8 ++++----
+ src/hb-aat-layout.cc            | 32 ++++++++++++++++----------------
+ src/hb-aat.h                    | 26 +++++++++++++-------------
+ test/api/test-aat-layout.c      | 28 ++++++++++++++--------------
+ 5 files changed, 52 insertions(+), 52 deletions(-)
+
+commit 54f4c17f0a932b0ca0317e1ad5e5e43a11a83fd1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 23 12:05:06 2018 +0330
+
+    [feat] Rename API uses of setting to selector
+
+ docs/harfbuzz-sections.txt      |  6 +--
+ src/hb-aat-layout-feat-table.hh | 52 ++++++++++++------------
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ src/hb-aat-layout.cc            | 88
+ ++++++++++++++++++++---------------------
+ src/hb-aat-layout.hh            |  4 +-
+ src/hb-aat-map.cc               |  2 +-
+ src/hb-aat-map.hh               |  2 +-
+ src/hb-aat.h                    | 20 +++++-----
+ test/api/test-aat-layout.c      | 46 ++++++++++-----------
+ 9 files changed, 111 insertions(+), 111 deletions(-)
+
+commit 9c64b216ec7ae2c2c124ebd00dc6fa568752be78
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 23 11:44:53 2018 +0330
+
+    [feat] Apply renamings and add documentation
+
+ docs/harfbuzz-sections.txt | 10 ++++++++++
+ src/hb-aat-layout.cc       | 44
+ ++++++++++++++++++++++++++++++++++++++------
+ src/hb-aat.h               |  6 +++---
+ test/api/test-aat-layout.c | 28 ++++++++++++++--------------
+ 4 files changed, 65 insertions(+), 23 deletions(-)
+
+commit a8726cb4830f51a820db4bc6346ed09c91493817
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 17 14:23:11 2018 +0330
+
+    [feat] Use bsearch
+
+ src/hb-aat-layout-feat-table.hh | 36 ++++++++++++++++++++++--------------
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ src/hb.hh                       |  2 ++
+ 3 files changed, 25 insertions(+), 15 deletions(-)
+
+commit 4009a05ca7de21fff2176621597cd0cd01e9d80e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 17 11:30:50 2018 +0330
+
+    [feat] Address Behdad comments
+
+ src/hb-aat-layout-feat-table.hh | 114 ++++---
+ src/hb-aat-layout.cc            |  14 +-
+ src/hb-aat.h                    | 673
+ +++++++++++++++++-----------------------
+ test/api/test-aat-layout.c      |  88 +++---
+ 4 files changed, 423 insertions(+), 466 deletions(-)
+
+commit 19b6025534a98df96d67eee45c5c1ea6fbc1cc43
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 17 01:07:09 2018 +0330
+
+    [feat] Address @behdad comments
+
+ src/Makefile.sources            |   2 +-
+ src/hb-aat-layout-feat-table.hh |  82 +++----
+ src/hb-aat-layout-morx-table.hh |   2 +-
+ src/hb-aat-layout.cc            | 104 ++++----
+ src/hb-aat-map.cc               |   2 +-
+ src/hb-aat.h                    | 533
+ ++++++++++++----------------------------
+ src/hb-ot.h                     |   1 -
+ test/api/test-aat-layout.c      |  84 +++----
+ 8 files changed, 282 insertions(+), 528 deletions(-)
+
+commit 9212ec203c948e290a1d92b701619ccdbc89377c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 9 00:50:10 2018 +0330
+
+    [feat] Complete feature types list
+
+ src/hb-aat-layout-morx-table.hh |   2 +-
+ src/hb-aat-layout.cc            | 154 ++++-----
+ src/hb-aat.h                    | 697
+ ++++++++++++++++++++++++++++++++++++++--
+ 3 files changed, 752 insertions(+), 101 deletions(-)
+
+commit fbad794bd2c574363a0c5c5fefabce764496f93c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 22:24:42 2018 +0330
+
+    [feat] Add feature iteration API
+
+ src/hb-aat-layout-feat-table.hh | 36 +++++++++++++++++++++--------
+ src/hb-aat-layout.cc            | 26 +++++++++++----------
+ src/hb-aat.h                    | 23 +++++++++++++++++--
+ test/api/test-aat-layout.c      | 51
+ +++++++++++++++++++++++++++--------------
+ 4 files changed, 96 insertions(+), 40 deletions(-)
+
+commit 7a0471aa356bcd062d31a59bdb19c335249116c7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 21:38:54 2018 +0330
+
+    [feat] Turn AAT feature id into enum
+
+ src/hb-aat-layout-feat-table.hh |  20 ++---
+ src/hb-aat-layout-morx-table.hh |  10 +--
+ src/hb-aat-layout.cc            | 170
+ ++++++++++++++++++++--------------------
+ src/hb-aat-layout.hh            |   6 +-
+ src/hb-aat-map.cc               |   2 +-
+ src/hb-aat-map.hh               |   4 +-
+ src/hb-aat.h                    |  64 +++++++++------
+ test/api/test-aat-layout.c      |   8 +-
+ test/api/test-c.c               |   1 +
+ 9 files changed, 150 insertions(+), 135 deletions(-)
+
+commit b233fa4bc9cdb1c6677b37106d96d878d6e03bfd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 20:02:57 2018 +0330
+
+    [feat] Rename records to selectors as @drott
+
+ src/hb-aat-layout-feat-table.hh | 20 ++++++++++----------
+ src/hb-aat-layout.cc            | 10 +++++-----
+ src/hb-aat.h                    |  4 ++--
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+commit a157b3e4ebd57ad29f217c4cef6519e7398cfa5c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 19:56:16 2018 +0330
+
+    [feat] Apply @behdad comments
+
+ src/Makefile.sources              |  2 +-
+ src/hb-aat-layout-feat-table.hh   |  1 +
+ src/hb-aat-layout.cc              | 16 ++++++++--------
+ src/hb-aat-layout.hh              |  2 +-
+ src/hb-aat-map.hh                 |  2 +-
+ src/{hb-aat-layout.h => hb-aat.h} | 22 +++++++++++++---------
+ src/hb-ot.h                       |  1 +
+ test/api/test-aat-layout.c        | 14 +++++++-------
+ test/api/test-c.c                 |  1 -
+ 9 files changed, 33 insertions(+), 28 deletions(-)
+
+commit 3aff3f822f0d7bf7a2b5160ad93df3fe413c7c47
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 19:20:20 2018 +0330
+
+    [feat] Apply @drott and @jfkthame comments
+
+ src/hb-aat-layout-feat-table.hh | 14 ++++++--------
+ src/hb-aat-layout.cc            | 12 +++++++-----
+ src/hb-aat-layout.h             | 10 +++++-----
+ test/api/test-aat-layout.c      |  4 ++--
+ 4 files changed, 20 insertions(+), 20 deletions(-)
+
+commit b791bbbae47aa19709da640a1dc5e84590c5c2c2
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 15:15:56 2018 +0330
+
+    [feat] Apply @jfkthame reviews
+
+ src/hb-aat-layout-feat-table.hh |  27 +++++++++++++++------------
+ src/hb-aat-layout.cc            |  23 ++++++++++++-----------
+ src/hb-aat-layout.h             |  14 +++++++++-----
+ test/api/fonts/aat-feat.ttf     | Bin 0 -> 1132 bytes
+ test/api/test-aat-layout.c      |  30 ++++++++++++++++++------------
+ 5 files changed, 54 insertions(+), 40 deletions(-)
+
+commit 95abd53758e281325b9124f0942aafb382a89090
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 13:14:29 2018 +0330
+
+    [feat] Expose public API
+
+    * hb_aat_get_feature_settings
+
+ src/Makefile.sources            |  1 +
+ src/hb-aat-layout-feat-table.hh | 68 ++++++++++++++++++++++++++++++-
+ src/hb-aat-layout-morx-table.hh |  6 +--
+ src/hb-aat-layout.cc            | 33 +++++++++++++++
+ src/hb-aat-layout.h             | 75 ++++++++++++++++++++++++++++++++++
+ src/hb-aat-layout.hh            |  7 ++--
+ src/hb-aat-map.hh               |  5 ++-
+ src/hb-ot-face.hh               |  1 +
+ test/api/Makefile.am            |  1 +
+ test/api/test-aat-layout.c      | 89
+ +++++++++++++++++++++++++++++++++++++++++
+ test/api/test-c.c               |  1 +
+ 11 files changed, 278 insertions(+), 9 deletions(-)
+
+commit 264c4a539cbfd8d5e5f143206d9d27230a186897
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 00:30:08 2018 -0500
+
+    [test] Reorder test suites
+
+    aots is less interesting.  Run text-rendering-tests before aots.
+
+ test/shaping/data/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9326912941e5927bcfb4689689c954b9a3995baa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 00:27:23 2018 -0500
+
+    [kerx] Fix crash
+
+ src/hb-machinery.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 6ee401049d475b2a2d9c859e6dbf8ff2750a1609
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 25 00:21:13 2018 -0500
+
+    Simplify sanitize set_object() / fix bots
+
+ src/hb-machinery.hh | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit c5a6b355e165e90d8d90454ceeca7b100282945f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 23:49:23 2018 -0500
+
+    [kerx] Port to hb_sanitize_with_object_t
+
+ src/hb-aat-layout-kerx-table.hh | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+commit c405ed0509afaa7c3846e8e461bedfbceb0cd937
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 23:46:15 2018 -0500
+
+    [morx] Port to hb_sanitize_with_object_t
+
+ src/hb-aat-layout-morx-table.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 1e8994221fb5cfdb1902d5249c7a75cde6d6e3c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 23:38:06 2018 -0500
+
+    Add hb_sanitize_with_object_t
+
+    Context manager.
+
+ src/hb-machinery.hh | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+commit b3c5affc05a3c7bbcfbd98521703d3d3447fcd7d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 23:34:34 2018 -0500
+
+    Simplify sanitize set_object()
+
+ src/hb-aat-layout-kerx-table.hh | 12 ++++++------
+ src/hb-aat-layout-morx-table.hh | 10 +++++-----
+ src/hb-machinery.hh             | 26 +++++++++++++-------------
+ 3 files changed, 24 insertions(+), 24 deletions(-)
+
+commit 3d3097269995aa227b4b198d4da2baf942b65c66
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 23:12:28 2018 -0500
+
+    [aat] Skip terminator in VarSizedBinSearchArray<>
+
+    Fixes shaping with Apple Chancery on 10.13 again.  In that font,
+    there was a terminator segment, that was tripping off sanitize().
+
+ src/hb-aat-layout-common.hh |  6 ++++++
+ src/hb-open-type.hh         | 21 ++++++++++++++++++++-
+ 2 files changed, 26 insertions(+), 1 deletion(-)
+
+commit 4202a3cde3b6065124feb7f4c662563de1e08126
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:48:34 2018 -0500
+
+    Minor
+
+ src/hb-open-type.hh | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+commit 1c2302bbf1d2d0e66f49ab54ad98d1b61bc5603d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:32:17 2018 -0500
+
+    [debug] Print function in return_trace()
+
+ src/hb-debug.hh | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+commit 748198a6718adbb200ee24ac013c617f62c946a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:16:59 2018 -0500
+
+    Revert "[aat.morx] Remove set_object() business"
+
+    This reverts commit ae8ed58a6e53441d9ccbf67afd8a00b815cde99e.
+
+    Apparently this broke Apple Chancery from OS X 10.12 :(.
+    Investigating...
+
+ src/hb-aat-layout-morx-table.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit c8a2dc820eb0ee3124e3762cb1167ac9e528ad28
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:16:53 2018 -0500
+
+    Revert "[aat.kerx] Remove kerx subtable boundary enforcement"
+
+    This reverts commit 15905a2a2998f7ddd964f920a4828602235d6b00.
+
+ src/hb-aat-layout-kerx-table.hh | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+commit 9eeebd8ddedb96c03860ce7eb5500aafa3969d6b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:16:47 2018 -0500
+
+    Revert "[sanitize] Remove now-unused set_object() machinery"
+
+    This reverts commit bbdb6edb3e1cea4c5b7076c4f6b3e6998ae36dae.
+
+ src/hb-machinery.hh | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+commit 248ce22857c8918bf3468ef48d906de4c19c3d4d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 22:01:06 2018 -0500
+
+    [tests] Minor
+
+ test/shaping/run-tests.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f47c5da0aa04a88b37d9c3af4730204319a9a36b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 21:36:57 2018 -0500
+
+    [arrays] Use hb_array_t<> in all places with sub_array()
+
+ src/hb-aat-layout-lcar-table.hh |  6 +++---
+ src/hb-ot-layout-gdef-table.hh  | 14 ++++++++------
+ src/hb-ot-math-table.hh         | 10 ++++------
+ 3 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 3246a8ebbd900bcc3e3c70532eab0f406b8f5c4a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 21:32:00 2018 -0500
+
+    [arrays] Merge ArrayOf's sub_array into hb_array_t's
+
+ src/hb-dsalgs.hh    | 44 +++++++++++++++++++++++++++-----------------
+ src/hb-open-type.hh | 30 ++++++++++++++++++------------
+ 2 files changed, 45 insertions(+), 29 deletions(-)
+
+commit e6877e28cd30e89af7cce59d903184a5a01ec970
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 02:12:40 2018 +0330
+
+    [test] Add the missed aots fonts
+
+ test/shaping/data/aots/fonts/classdef1_font1.otf   | Bin 0 -> 6004 bytes
+ test/shaping/data/aots/fonts/classdef1_font2.otf   | Bin 0 -> 6020 bytes
+ test/shaping/data/aots/tests/classdef1_empty.tests |   2 +-
+ 3 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 825ea5a4607fafa11c56a72a82bda773f6b44e79
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 01:59:54 2018 +0330
+
+    [test] Merge 10.12.6 and 10.13.6 tests, update to Apple Chancery fix
+
+ test/shaping/data/in-house/Makefile.sources        |  3 +--
+ .../data/in-house/tests/macos-10.12.6.tests        | 11 ---------
+ .../data/in-house/tests/macos-10.13.6.tests        | 13 -----------
+ test/shaping/data/in-house/tests/macos.tests       | 26
+ ++++++++++++++++++++++
+ 4 files changed, 27 insertions(+), 26 deletions(-)
+
+commit bbdb6edb3e1cea4c5b7076c4f6b3e6998ae36dae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 17:15:38 2018 -0500
+
+    [sanitize] Remove now-unused set_object() machinery
+
+ src/hb-machinery.hh | 25 +------------------------
+ 1 file changed, 1 insertion(+), 24 deletions(-)
+
+commit 15905a2a2998f7ddd964f920a4828602235d6b00
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 17:14:39 2018 -0500
+
+    [aat.kerx] Remove kerx subtable boundary enforcement
+
+    Have not encountered fonts needing this, but same reasoning as
+    for morx (see previos commit.)
+
+ src/hb-aat-layout-kerx-table.hh | 21 ---------------------
+ 1 file changed, 21 deletions(-)
+
+commit ae8ed58a6e53441d9ccbf67afd8a00b815cde99e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 17:11:09 2018 -0500
+
+    [aat.morx] Remove set_object() business
+
+    With OS X 10.13 Apple Chancery fails to ligate if we limit each morx
+    sub-chain to its declared length.  Perhaps their newer compiler does
+    object-sharing across sub-chains.  Anyway, since that's a valid, if
+    unspecified, way to compile tables, remove enforcement.
+
+    Probably do the same with kern/kerx.
+
+ src/hb-aat-layout-morx-table.hh | 8 --------
+ 1 file changed, 8 deletions(-)
+
+commit b518e5af9f66414396752069bb8f43466a9236fa
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Nov 25 01:39:00 2018 +0330
+
+    Add 10.13.6 aat fonts tests and bot (#1409)
+
+ .circleci/config.yml                                     | 16
+ ++++++++++++++--
+ test/shaping/data/in-house/Makefile.sources              |  3 ++-
+ .../in-house/tests/{macos.tests => macos-10.12.6.tests}  |  2 --
+ test/shaping/data/in-house/tests/macos-10.13.6.tests     | 13
+ +++++++++++++
+ 4 files changed, 29 insertions(+), 5 deletions(-)
+
+commit b7f7950e8fc4b9e229b466ac2453d57b8da9a5a6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 15:56:17 2018 -0500
+
+    [aat] Add test for recent regression
+
+ test/shaping/data/in-house/tests/macos.tests | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit ea9512e61a7ed333b810918e74cce4c8bd2291b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 15:49:33 2018 -0500
+
+    [tests] Redo test runner logging a  bit
+
+ test/shaping/run-tests.py | 44
+ +++++++++++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 21 deletions(-)
+
+commit 5020affc3877d39377506245ecaf01a659eef82a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 15:42:11 2018 -0500
+
+    [tests] Minor
+
+ test/shaping/data/in-house/tests/macos.tests | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit ee3a3e10d45f5df1a74b65fbe3df77f8dd8f902e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 15:37:01 2018 -0500
+
+    [tests/shaping] Allow comments in test files
+
+    Line should start with "# ".
+
+ test/shaping/run-tests.py | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+commit ed900ee9afa0dabdbf6bf9d2af46c2343a16773f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 15:22:09 2018 -0500
+
+    [tests] Rename
+
+ test/shaping/data/in-house/Makefile.sources                         |
+ 2 +-
+ test/shaping/data/in-house/tests/{macos-10.12.tests => macos.tests} | 0
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 20edc70d537b01e8a384ee05673335f2f8a18238
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 14:52:34 2018 -0500
+
+    [morx/kerx] Fix sanitize regression
+
+    Broke in 8dcc1913a1670ede7b124f7b5b775d7ab8791386
+
+    If sanitizer is left with another object, it wouldn't work.
+
+    Better fix coming soon.
+
+ src/hb-aat-layout-kerx-table.hh | 6 +-----
+ src/hb-aat-layout-morx-table.hh | 4 +---
+ 2 files changed, 2 insertions(+), 8 deletions(-)
+
+commit 3cc14e78aeb1c70eb82891ab4513c0e7d0f59928
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 24 20:49:21 2018 +0330
+
+    [test] Enable more of aots tests (#1408)
+
+    The ones commented out in this change should've be passed :/
+    a closer look is needed.
+
+ test/shaping/data/aots/Makefile.sources            | 76
+ +++++++++++-----------
+ test/shaping/data/aots/hb-aots-tester.cpp          |  1 +
+ test/shaping/data/aots/tests/classdef1_empty.tests |  2 +-
+ test/shaping/data/aots/tests/gsub3_1_simple.tests  |  2 +-
+ .../data/aots/tests/lookupflag_ignore_attach.tests | 10 +--
+ 5 files changed, 46 insertions(+), 45 deletions(-)
+
+commit 24887d1115ee41cfad70577eb243382f6c23ab6e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 24 20:07:24 2018 +0330
+
+    Add Adobe AOTS tests (#1395)
+
+    Annotated OpenType Specification or aots,
+    https://github.com/adobe-type-tools/aots
+    provides a set of tests for OpenType specification, this change add
+    those tests in addition
+    to modified version of their HarfBuzz test runner for generating
+    harfbuzz project specific tests.
+
+ configure.ac                                       |   1 +
+ test/shaping/CMakeLists.txt                        |  13 +-
+ test/shaping/data/Makefile.am                      |   1 +
+ test/shaping/data/aots/COPYING                     |  13 +
+ test/shaping/data/aots/Makefile.am                 |  37 +++
+ test/shaping/data/aots/Makefile.sources            | 126 ++++++++
+ test/shaping/data/aots/fonts/classdef1_font3.otf   | Bin 0 -> 6060 bytes
+ test/shaping/data/aots/fonts/classdef1_font4.otf   | Bin 0 -> 5984 bytes
+ test/shaping/data/aots/fonts/classdef2_font1.otf   | Bin 0 -> 6004 bytes
+ test/shaping/data/aots/fonts/classdef2_font2.otf   | Bin 0 -> 6016 bytes
+ test/shaping/data/aots/fonts/classdef2_font3.otf   | Bin 0 -> 6052 bytes
+ test/shaping/data/aots/fonts/classdef2_font4.otf   | Bin 0 -> 5984 bytes
+ test/shaping/data/aots/fonts/cmap0_font1.otf       | Bin 0 -> 5196 bytes
+ test/shaping/data/aots/fonts/cmap10_font1.otf      | Bin 0 -> 4968 bytes
+ test/shaping/data/aots/fonts/cmap10_font2.otf      | Bin 0 -> 4960 bytes
+ test/shaping/data/aots/fonts/cmap12_font1.otf      | Bin 0 -> 4980 bytes
+ test/shaping/data/aots/fonts/cmap14_font1.otf      | Bin 0 -> 5028 bytes
+ test/shaping/data/aots/fonts/cmap2_font1.otf       | Bin 0 -> 6000 bytes
+ test/shaping/data/aots/fonts/cmap4_font1.otf       | Bin 0 -> 4964 bytes
+ test/shaping/data/aots/fonts/cmap4_font2.otf       | Bin 0 -> 4956 bytes
+ test/shaping/data/aots/fonts/cmap4_font3.otf       | Bin 0 -> 4956 bytes
+ test/shaping/data/aots/fonts/cmap4_font4.otf       | Bin 0 -> 4972 bytes
+ test/shaping/data/aots/fonts/cmap6_font1.otf       | Bin 0 -> 4948 bytes
+ test/shaping/data/aots/fonts/cmap6_font2.otf       | Bin 0 -> 4944 bytes
+ test/shaping/data/aots/fonts/cmap8_font1.otf       | Bin 0 -> 13224 bytes
+ .../data/aots/fonts/cmap_composition_font1.otf     | Bin 0 -> 5096 bytes
+ .../aots/fonts/cmap_subtableselection_font1.otf    | Bin 0 -> 6412 bytes
+ .../aots/fonts/cmap_subtableselection_font2.otf    | Bin 0 -> 6140 bytes
+ .../aots/fonts/cmap_subtableselection_font3.otf    | Bin 0 -> 5872 bytes
+ .../aots/fonts/cmap_subtableselection_font4.otf    | Bin 0 -> 5600 bytes
+ .../aots/fonts/cmap_subtableselection_font5.otf    | Bin 0 -> 5332 bytes
+ .../data/aots/fonts/gpos1_1_lookupflag_f1.otf      | Bin 0 -> 5208 bytes
+ test/shaping/data/aots/fonts/gpos1_1_simple_f1.otf | Bin 0 -> 5136 bytes
+ test/shaping/data/aots/fonts/gpos1_1_simple_f2.otf | Bin 0 -> 5136 bytes
+ test/shaping/data/aots/fonts/gpos1_1_simple_f3.otf | Bin 0 -> 5136 bytes
+ test/shaping/data/aots/fonts/gpos1_1_simple_f4.otf | Bin 0 -> 5136 bytes
+ test/shaping/data/aots/fonts/gpos1_2_font1.otf     | Bin 0 -> 5108 bytes
+ test/shaping/data/aots/fonts/gpos1_2_font2.otf     | Bin 0 -> 5148 bytes
+ test/shaping/data/aots/fonts/gpos2_1_font6.otf     | Bin 0 -> 5120 bytes
+ test/shaping/data/aots/fonts/gpos2_1_font7.otf     | Bin 0 -> 5132 bytes
+ .../data/aots/fonts/gpos2_1_lookupflag_f1.otf      | Bin 0 -> 5220 bytes
+ .../data/aots/fonts/gpos2_1_lookupflag_f2.otf      | Bin 0 -> 5220 bytes
+ .../data/aots/fonts/gpos2_1_next_glyph_f1.otf      | Bin 0 -> 5180 bytes
+ .../data/aots/fonts/gpos2_1_next_glyph_f2.otf      | Bin 0 -> 5176 bytes
+ test/shaping/data/aots/fonts/gpos2_1_simple_f1.otf | Bin 0 -> 5148 bytes
+ test/shaping/data/aots/fonts/gpos2_2_font1.otf     | Bin 0 -> 5148 bytes
+ test/shaping/data/aots/fonts/gpos2_2_font2.otf     | Bin 0 -> 5188 bytes
+ test/shaping/data/aots/fonts/gpos2_2_font3.otf     | Bin 0 -> 5188 bytes
+ test/shaping/data/aots/fonts/gpos2_2_font4.otf     | Bin 0 -> 5148 bytes
+ test/shaping/data/aots/fonts/gpos2_2_font5.otf     | Bin 0 -> 5140 bytes
+ test/shaping/data/aots/fonts/gpos3_font1.otf       | Bin 0 -> 5120 bytes
+ test/shaping/data/aots/fonts/gpos3_font2.otf       | Bin 0 -> 5160 bytes
+ test/shaping/data/aots/fonts/gpos3_font3.otf       | Bin 0 -> 5164 bytes
+ .../data/aots/fonts/gpos4_lookupflag_f1.otf        | Bin 0 -> 5256 bytes
+ .../data/aots/fonts/gpos4_lookupflag_f2.otf        | Bin 0 -> 5240 bytes
+ .../data/aots/fonts/gpos4_multiple_anchors_1.otf   | Bin 0 -> 5352 bytes
+ test/shaping/data/aots/fonts/gpos4_simple_1.otf    | Bin 0 -> 5200 bytes
+ test/shaping/data/aots/fonts/gpos5_font1.otf       | Bin 0 -> 5284 bytes
+ test/shaping/data/aots/fonts/gpos6_font1.otf       | Bin 0 -> 5176 bytes
+ test/shaping/data/aots/fonts/gpos7_1_font1.otf     | Bin 0 -> 5160 bytes
+ test/shaping/data/aots/fonts/gpos9_font1.otf       | Bin 0 -> 5096 bytes
+ test/shaping/data/aots/fonts/gpos9_font2.otf       | Bin 0 -> 5124 bytes
+ .../data/aots/fonts/gpos_chaining1_boundary_f1.otf | Bin 0 -> 5496 bytes
+ .../data/aots/fonts/gpos_chaining1_boundary_f2.otf | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gpos_chaining1_boundary_f3.otf | Bin 0 -> 5496 bytes
+ .../data/aots/fonts/gpos_chaining1_boundary_f4.otf | Bin 0 -> 5496 bytes
+ .../aots/fonts/gpos_chaining1_lookupflag_f1.otf    | Bin 0 -> 5520 bytes
+ .../fonts/gpos_chaining1_multiple_subrules_f1.otf  | Bin 0 -> 5592 bytes
+ .../fonts/gpos_chaining1_multiple_subrules_f2.otf  | Bin 0 -> 5592 bytes
+ .../aots/fonts/gpos_chaining1_next_glyph_f1.otf    | Bin 0 -> 5540 bytes
+ .../data/aots/fonts/gpos_chaining1_simple_f1.otf   | Bin 0 -> 5488 bytes
+ .../data/aots/fonts/gpos_chaining1_simple_f2.otf   | Bin 0 -> 5488 bytes
+ .../aots/fonts/gpos_chaining1_successive_f1.otf    | Bin 0 -> 5524 bytes
+ .../data/aots/fonts/gpos_chaining2_boundary_f1.otf | Bin 0 -> 5704 bytes
+ .../data/aots/fonts/gpos_chaining2_boundary_f2.otf | Bin 0 -> 5708 bytes
+ .../data/aots/fonts/gpos_chaining2_boundary_f3.otf | Bin 0 -> 5704 bytes
+ .../data/aots/fonts/gpos_chaining2_boundary_f4.otf | Bin 0 -> 5704 bytes
+ .../aots/fonts/gpos_chaining2_lookupflag_f1.otf    | Bin 0 -> 5728 bytes
+ .../fonts/gpos_chaining2_multiple_subrules_f1.otf  | Bin 0 -> 5800 bytes
+ .../fonts/gpos_chaining2_multiple_subrules_f2.otf  | Bin 0 -> 5800 bytes
+ .../aots/fonts/gpos_chaining2_next_glyph_f1.otf    | Bin 0 -> 5744 bytes
+ .../data/aots/fonts/gpos_chaining2_simple_f1.otf   | Bin 0 -> 5696 bytes
+ .../data/aots/fonts/gpos_chaining2_simple_f2.otf   | Bin 0 -> 5696 bytes
+ .../aots/fonts/gpos_chaining2_successive_f1.otf    | Bin 0 -> 5732 bytes
+ .../data/aots/fonts/gpos_chaining3_boundary_f1.otf | Bin 0 -> 5504 bytes
+ .../data/aots/fonts/gpos_chaining3_boundary_f2.otf | Bin 0 -> 5508 bytes
+ .../data/aots/fonts/gpos_chaining3_boundary_f3.otf | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gpos_chaining3_boundary_f4.otf | Bin 0 -> 5500 bytes
+ .../aots/fonts/gpos_chaining3_lookupflag_f1.otf    | Bin 0 -> 5548 bytes
+ .../aots/fonts/gpos_chaining3_next_glyph_f1.otf    | Bin 0 -> 5524 bytes
+ .../data/aots/fonts/gpos_chaining3_simple_f1.otf   | Bin 0 -> 5496 bytes
+ .../data/aots/fonts/gpos_chaining3_simple_f2.otf   | Bin 0 -> 5516 bytes
+ .../aots/fonts/gpos_chaining3_successive_f1.otf    | Bin 0 -> 5544 bytes
+ .../data/aots/fonts/gpos_context1_boundary_f1.otf  | Bin 0 -> 5480 bytes
+ .../data/aots/fonts/gpos_context1_boundary_f2.otf  | Bin 0 -> 5480 bytes
+ .../data/aots/fonts/gpos_context1_expansion_f1.otf | Bin 0 -> 5492 bytes
+ .../aots/fonts/gpos_context1_lookupflag_f1.otf     | Bin 0 -> 5508 bytes
+ .../aots/fonts/gpos_context1_lookupflag_f2.otf     | Bin 0 -> 5500 bytes
+ .../fonts/gpos_context1_multiple_subrules_f1.otf   | Bin 0 -> 5568 bytes
+ .../fonts/gpos_context1_multiple_subrules_f2.otf   | Bin 0 -> 5568 bytes
+ .../aots/fonts/gpos_context1_next_glyph_f1.otf     | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gpos_context1_simple_f1.otf    | Bin 0 -> 5476 bytes
+ .../data/aots/fonts/gpos_context1_simple_f2.otf    | Bin 0 -> 5468 bytes
+ .../aots/fonts/gpos_context1_successive_f1.otf     | Bin 0 -> 5508 bytes
+ .../data/aots/fonts/gpos_context2_boundary_f1.otf  | Bin 0 -> 5492 bytes
+ .../data/aots/fonts/gpos_context2_boundary_f2.otf  | Bin 0 -> 5496 bytes
+ .../data/aots/fonts/gpos_context2_classes_f1.otf   | Bin 0 -> 5540 bytes
+ .../data/aots/fonts/gpos_context2_classes_f2.otf   | Bin 0 -> 5564 bytes
+ .../data/aots/fonts/gpos_context2_expansion_f1.otf | Bin 0 -> 5524 bytes
+ .../aots/fonts/gpos_context2_lookupflag_f1.otf     | Bin 0 -> 5540 bytes
+ .../aots/fonts/gpos_context2_lookupflag_f2.otf     | Bin 0 -> 5532 bytes
+ .../fonts/gpos_context2_multiple_subrules_f1.otf   | Bin 0 -> 5600 bytes
+ .../fonts/gpos_context2_multiple_subrules_f2.otf   | Bin 0 -> 5600 bytes
+ .../aots/fonts/gpos_context2_next_glyph_f1.otf     | Bin 0 -> 5512 bytes
+ .../data/aots/fonts/gpos_context2_simple_f1.otf    | Bin 0 -> 5508 bytes
+ .../data/aots/fonts/gpos_context2_simple_f2.otf    | Bin 0 -> 5484 bytes
+ .../aots/fonts/gpos_context2_successive_f1.otf     | Bin 0 -> 5544 bytes
+ .../data/aots/fonts/gpos_context3_boundary_f1.otf  | Bin 0 -> 5476 bytes
+ .../data/aots/fonts/gpos_context3_boundary_f2.otf  | Bin 0 -> 5472 bytes
+ .../aots/fonts/gpos_context3_lookupflag_f1.otf     | Bin 0 -> 5512 bytes
+ .../aots/fonts/gpos_context3_lookupflag_f2.otf     | Bin 0 -> 5504 bytes
+ .../aots/fonts/gpos_context3_next_glyph_f1.otf     | Bin 0 -> 5496 bytes
+ .../data/aots/fonts/gpos_context3_simple_f1.otf    | Bin 0 -> 5480 bytes
+ .../aots/fonts/gpos_context3_successive_f1.otf     | Bin 0 -> 5516 bytes
+ .../data/aots/fonts/gsub1_1_lookupflag_f1.otf      | Bin 0 -> 5208 bytes
+ test/shaping/data/aots/fonts/gsub1_1_modulo_f1.otf | Bin 0 -> 5216 bytes
+ test/shaping/data/aots/fonts/gsub1_1_simple_f1.otf | Bin 0 -> 5136 bytes
+ .../data/aots/fonts/gsub1_2_lookupflag_f1.otf      | Bin 0 -> 5212 bytes
+ test/shaping/data/aots/fonts/gsub1_2_simple_f1.otf | Bin 0 -> 5140 bytes
+ .../data/aots/fonts/gsub2_1_lookupflag_f1.otf      | Bin 0 -> 5224 bytes
+ .../aots/fonts/gsub2_1_multiple_sequences_f1.otf   | Bin 0 -> 5248 bytes
+ test/shaping/data/aots/fonts/gsub2_1_simple_f1.otf | Bin 0 -> 5144 bytes
+ .../data/aots/fonts/gsub3_1_lookupflag_f1.otf      | Bin 0 -> 5224 bytes
+ .../data/aots/fonts/gsub3_1_multiple_f1.otf        | Bin 0 -> 5168 bytes
+ test/shaping/data/aots/fonts/gsub3_1_simple_f1.otf | Bin 0 -> 5144 bytes
+ .../data/aots/fonts/gsub4_1_lookupflag_f1.otf      | Bin 0 -> 5220 bytes
+ .../aots/fonts/gsub4_1_multiple_ligatures_f1.otf   | Bin 0 -> 5252 bytes
+ .../aots/fonts/gsub4_1_multiple_ligatures_f2.otf   | Bin 0 -> 5252 bytes
+ .../aots/fonts/gsub4_1_multiple_ligsets_f1.otf     | Bin 0 -> 5240 bytes
+ test/shaping/data/aots/fonts/gsub4_1_simple_f1.otf | Bin 0 -> 5148 bytes
+ test/shaping/data/aots/fonts/gsub7_font1.otf       | Bin 0 -> 5096 bytes
+ test/shaping/data/aots/fonts/gsub7_font2.otf       | Bin 0 -> 5116 bytes
+ .../data/aots/fonts/gsub_chaining1_boundary_f1.otf | Bin 0 -> 5516 bytes
+ .../data/aots/fonts/gsub_chaining1_boundary_f2.otf | Bin 0 -> 5520 bytes
+ .../data/aots/fonts/gsub_chaining1_boundary_f3.otf | Bin 0 -> 5520 bytes
+ .../data/aots/fonts/gsub_chaining1_boundary_f4.otf | Bin 0 -> 5520 bytes
+ .../aots/fonts/gsub_chaining1_lookupflag_f1.otf    | Bin 0 -> 5544 bytes
+ .../fonts/gsub_chaining1_multiple_subrules_f1.otf  | Bin 0 -> 5616 bytes
+ .../fonts/gsub_chaining1_multiple_subrules_f2.otf  | Bin 0 -> 5616 bytes
+ .../aots/fonts/gsub_chaining1_next_glyph_f1.otf    | Bin 0 -> 5560 bytes
+ .../data/aots/fonts/gsub_chaining1_simple_f1.otf   | Bin 0 -> 5508 bytes
+ .../data/aots/fonts/gsub_chaining1_simple_f2.otf   | Bin 0 -> 5512 bytes
+ .../aots/fonts/gsub_chaining1_successive_f1.otf    | Bin 0 -> 5544 bytes
+ .../data/aots/fonts/gsub_chaining2_boundary_f1.otf | Bin 0 -> 5724 bytes
+ .../data/aots/fonts/gsub_chaining2_boundary_f2.otf | Bin 0 -> 5728 bytes
+ .../data/aots/fonts/gsub_chaining2_boundary_f3.otf | Bin 0 -> 5728 bytes
+ .../data/aots/fonts/gsub_chaining2_boundary_f4.otf | Bin 0 -> 5728 bytes
+ .../aots/fonts/gsub_chaining2_lookupflag_f1.otf    | Bin 0 -> 5752 bytes
+ .../fonts/gsub_chaining2_multiple_subrules_f1.otf  | Bin 0 -> 5824 bytes
+ .../fonts/gsub_chaining2_multiple_subrules_f2.otf  | Bin 0 -> 5824 bytes
+ .../aots/fonts/gsub_chaining2_next_glyph_f1.otf    | Bin 0 -> 5764 bytes
+ .../data/aots/fonts/gsub_chaining2_simple_f1.otf   | Bin 0 -> 5716 bytes
+ .../data/aots/fonts/gsub_chaining2_simple_f2.otf   | Bin 0 -> 5720 bytes
+ .../aots/fonts/gsub_chaining2_successive_f1.otf    | Bin 0 -> 5752 bytes
+ .../data/aots/fonts/gsub_chaining3_boundary_f1.otf | Bin 0 -> 5528 bytes
+ .../data/aots/fonts/gsub_chaining3_boundary_f2.otf | Bin 0 -> 5532 bytes
+ .../data/aots/fonts/gsub_chaining3_boundary_f3.otf | Bin 0 -> 5524 bytes
+ .../data/aots/fonts/gsub_chaining3_boundary_f4.otf | Bin 0 -> 5524 bytes
+ .../aots/fonts/gsub_chaining3_lookupflag_f1.otf    | Bin 0 -> 5572 bytes
+ .../aots/fonts/gsub_chaining3_next_glyph_f1.otf    | Bin 0 -> 5548 bytes
+ .../data/aots/fonts/gsub_chaining3_simple_f1.otf   | Bin 0 -> 5520 bytes
+ .../data/aots/fonts/gsub_chaining3_simple_f2.otf   | Bin 0 -> 5540 bytes
+ .../aots/fonts/gsub_chaining3_successive_f1.otf    | Bin 0 -> 5568 bytes
+ .../data/aots/fonts/gsub_context1_boundary_f1.otf  | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gsub_context1_boundary_f2.otf  | Bin 0 -> 5504 bytes
+ .../data/aots/fonts/gsub_context1_expansion_f1.otf | Bin 0 -> 5516 bytes
+ .../aots/fonts/gsub_context1_lookupflag_f1.otf     | Bin 0 -> 5532 bytes
+ .../aots/fonts/gsub_context1_lookupflag_f2.otf     | Bin 0 -> 5524 bytes
+ .../fonts/gsub_context1_multiple_subrules_f1.otf   | Bin 0 -> 5592 bytes
+ .../fonts/gsub_context1_multiple_subrules_f2.otf   | Bin 0 -> 5592 bytes
+ .../aots/fonts/gsub_context1_next_glyph_f1.otf     | Bin 0 -> 5520 bytes
+ .../data/aots/fonts/gsub_context1_simple_f1.otf    | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gsub_context1_simple_f2.otf    | Bin 0 -> 5492 bytes
+ .../aots/fonts/gsub_context1_successive_f1.otf     | Bin 0 -> 5528 bytes
+ .../data/aots/fonts/gsub_context2_boundary_f1.otf  | Bin 0 -> 5516 bytes
+ .../data/aots/fonts/gsub_context2_boundary_f2.otf  | Bin 0 -> 5516 bytes
+ .../data/aots/fonts/gsub_context2_classes_f1.otf   | Bin 0 -> 5564 bytes
+ .../data/aots/fonts/gsub_context2_classes_f2.otf   | Bin 0 -> 5584 bytes
+ .../data/aots/fonts/gsub_context2_expansion_f1.otf | Bin 0 -> 5544 bytes
+ .../aots/fonts/gsub_context2_lookupflag_f1.otf     | Bin 0 -> 5560 bytes
+ .../aots/fonts/gsub_context2_lookupflag_f2.otf     | Bin 0 -> 5552 bytes
+ .../fonts/gsub_context2_multiple_subrules_f1.otf   | Bin 0 -> 5620 bytes
+ .../fonts/gsub_context2_multiple_subrules_f2.otf   | Bin 0 -> 5620 bytes
+ .../aots/fonts/gsub_context2_next_glyph_f1.otf     | Bin 0 -> 5536 bytes
+ .../data/aots/fonts/gsub_context2_simple_f1.otf    | Bin 0 -> 5528 bytes
+ .../data/aots/fonts/gsub_context2_simple_f2.otf    | Bin 0 -> 5504 bytes
+ .../aots/fonts/gsub_context2_successive_f1.otf     | Bin 0 -> 5568 bytes
+ .../data/aots/fonts/gsub_context3_boundary_f1.otf  | Bin 0 -> 5500 bytes
+ .../data/aots/fonts/gsub_context3_boundary_f2.otf  | Bin 0 -> 5496 bytes
+ .../aots/fonts/gsub_context3_lookupflag_f1.otf     | Bin 0 -> 5536 bytes
+ .../aots/fonts/gsub_context3_lookupflag_f2.otf     | Bin 0 -> 5528 bytes
+ .../aots/fonts/gsub_context3_next_glyph_f1.otf     | Bin 0 -> 5520 bytes
+ .../data/aots/fonts/gsub_context3_simple_f1.otf    | Bin 0 -> 5504 bytes
+ .../aots/fonts/gsub_context3_successive_f1.otf     | Bin 0 -> 5540 bytes
+ .../aots/fonts/lookupflag_ignore_attach_f1.otf     | Bin 0 -> 5416 bytes
+ .../data/aots/fonts/lookupflag_ignore_base_f1.otf  | Bin 0 -> 5256 bytes
+ .../fonts/lookupflag_ignore_combination_f1.otf     | Bin 0 -> 5408 bytes
+ .../aots/fonts/lookupflag_ignore_ligatures_f1.otf  | Bin 0 -> 5320 bytes
+ .../data/aots/fonts/lookupflag_ignore_marks_f1.otf | Bin 0 -> 5288 bytes
+ test/shaping/data/aots/hb-aots-tester.cpp          | 343
+ +++++++++++++++++++++
+ test/shaping/data/aots/tests/classdef1.tests       |   1 +
+ test/shaping/data/aots/tests/classdef1_empty.tests |   1 +
+ .../data/aots/tests/classdef1_multiple.tests       |   1 +
+ .../shaping/data/aots/tests/classdef1_single.tests |   1 +
+ test/shaping/data/aots/tests/classdef2.tests       |   1 +
+ test/shaping/data/aots/tests/classdef2_empty.tests |   1 +
+ .../data/aots/tests/classdef2_multiple.tests       |   1 +
+ .../shaping/data/aots/tests/classdef2_single.tests |   1 +
+ .../data/aots/tests/gpos1_1_lookupflag.tests       |   1 +
+ test/shaping/data/aots/tests/gpos1_1_simple.tests  |   4 +
+ test/shaping/data/aots/tests/gpos1_2.tests         |   1 +
+ .../data/aots/tests/gpos1_2_lookupflag.tests       |   1 +
+ test/shaping/data/aots/tests/gpos2_1.tests         |   2 +
+ .../data/aots/tests/gpos2_1_lookupflag.tests       |   2 +
+ .../data/aots/tests/gpos2_1_next_glyph.tests       |   2 +
+ test/shaping/data/aots/tests/gpos2_1_simple.tests  |   2 +
+ test/shaping/data/aots/tests/gpos2_2.tests         |   5 +
+ test/shaping/data/aots/tests/gpos3.tests           |  11 +
+ .../shaping/data/aots/tests/gpos3_lookupflag.tests |   2 +
+ .../shaping/data/aots/tests/gpos4_lookupflag.tests |   2 +
+ .../data/aots/tests/gpos4_multiple_anchors.tests   |   1 +
+ test/shaping/data/aots/tests/gpos4_simple.tests    |   5 +
+ test/shaping/data/aots/tests/gpos5.tests           |   2 +
+ test/shaping/data/aots/tests/gpos6.tests           |   3 +
+ test/shaping/data/aots/tests/gpos7_1.tests         |   2 +
+ test/shaping/data/aots/tests/gpos9.tests           |   2 +
+ .../data/aots/tests/gpos_chaining1_boundary.tests  |   4 +
+ .../aots/tests/gpos_chaining1_lookupflag.tests     |   1 +
+ .../tests/gpos_chaining1_multiple_subrules.tests   |   2 +
+ .../aots/tests/gpos_chaining1_next_glyph.tests     |   1 +
+ .../data/aots/tests/gpos_chaining1_simple.tests    |  11 +
+ .../aots/tests/gpos_chaining1_successive.tests     |   1 +
+ .../data/aots/tests/gpos_chaining2_boundary.tests  |   4 +
+ .../aots/tests/gpos_chaining2_lookupflag.tests     |   1 +
+ .../tests/gpos_chaining2_multiple_subrules.tests   |   2 +
+ .../aots/tests/gpos_chaining2_next_glyph.tests     |   1 +
+ .../data/aots/tests/gpos_chaining2_simple.tests    |  11 +
+ .../aots/tests/gpos_chaining2_successive.tests     |   1 +
+ .../data/aots/tests/gpos_chaining3_boundary.tests  |   4 +
+ .../aots/tests/gpos_chaining3_lookupflag.tests     |   1 +
+ .../aots/tests/gpos_chaining3_next_glyph.tests     |   1 +
+ .../data/aots/tests/gpos_chaining3_simple.tests    |  11 +
+ .../aots/tests/gpos_chaining3_successive.tests     |   1 +
+ .../data/aots/tests/gpos_context1_boundary.tests   |   2 +
+ .../data/aots/tests/gpos_context1_expansion.tests  |   1 +
+ .../data/aots/tests/gpos_context1_lookupflag.tests |   2 +
+ .../tests/gpos_context1_multiple_subrules.tests    |   2 +
+ .../data/aots/tests/gpos_context1_next_glyph.tests |   1 +
+ .../data/aots/tests/gpos_context1_simple.tests     |   3 +
+ .../data/aots/tests/gpos_context1_successive.tests |   1 +
+ .../data/aots/tests/gpos_context2_boundary.tests   |   2 +
+ .../data/aots/tests/gpos_context2_classes.tests    |   2 +
+ .../data/aots/tests/gpos_context2_expansion.tests  |   1 +
+ .../data/aots/tests/gpos_context2_lookupflag.tests |   2 +
+ .../tests/gpos_context2_multiple_subrules.tests    |   2 +
+ .../data/aots/tests/gpos_context2_next_glyph.tests |   1 +
+ .../data/aots/tests/gpos_context2_simple.tests     |   3 +
+ .../data/aots/tests/gpos_context2_successive.tests |   1 +
+ .../data/aots/tests/gpos_context3_boundary.tests   |   2 +
+ .../data/aots/tests/gpos_context3_lookupflag.tests |   2 +
+ .../data/aots/tests/gpos_context3_next_glyph.tests |   1 +
+ .../data/aots/tests/gpos_context3_simple.tests     |   2 +
+ .../data/aots/tests/gpos_context3_successive.tests |   1 +
+ .../data/aots/tests/gsub1_1_lookupflag.tests       |   1 +
+ test/shaping/data/aots/tests/gsub1_1_modulo.tests  |   1 +
+ test/shaping/data/aots/tests/gsub1_1_simple.tests  |   1 +
+ .../data/aots/tests/gsub1_2_lookupflag.tests       |   1 +
+ test/shaping/data/aots/tests/gsub1_2_simple.tests  |   1 +
+ .../data/aots/tests/gsub2_1_lookupflag.tests       |   1 +
+ .../aots/tests/gsub2_1_multiple_sequences.tests    |   1 +
+ test/shaping/data/aots/tests/gsub2_1_simple.tests  |   2 +
+ .../data/aots/tests/gsub3_1_lookupflag.tests       |   1 +
+ .../shaping/data/aots/tests/gsub3_1_multiple.tests |   1 +
+ test/shaping/data/aots/tests/gsub3_1_simple.tests  |   1 +
+ .../data/aots/tests/gsub4_1_lookupflag.tests       |   1 +
+ .../aots/tests/gsub4_1_multiple_ligatures.tests    |   2 +
+ .../data/aots/tests/gsub4_1_multiple_ligsets.tests |   1 +
+ test/shaping/data/aots/tests/gsub4_1_simple.tests  |   1 +
+ test/shaping/data/aots/tests/gsub7.tests           |   2 +
+ .../data/aots/tests/gsub_chaining1_boundary.tests  |   4 +
+ .../aots/tests/gsub_chaining1_lookupflag.tests     |   1 +
+ .../tests/gsub_chaining1_multiple_subrules.tests   |   2 +
+ .../aots/tests/gsub_chaining1_next_glyph.tests     |   1 +
+ .../data/aots/tests/gsub_chaining1_simple.tests    |  11 +
+ .../aots/tests/gsub_chaining1_successive.tests     |   1 +
+ .../data/aots/tests/gsub_chaining2_boundary.tests  |   4 +
+ .../aots/tests/gsub_chaining2_lookupflag.tests     |   1 +
+ .../tests/gsub_chaining2_multiple_subrules.tests   |   2 +
+ .../aots/tests/gsub_chaining2_next_glyph.tests     |   1 +
+ .../data/aots/tests/gsub_chaining2_simple.tests    |  11 +
+ .../aots/tests/gsub_chaining2_successive.tests     |   1 +
+ .../data/aots/tests/gsub_chaining3_boundary.tests  |   4 +
+ .../aots/tests/gsub_chaining3_lookupflag.tests     |   1 +
+ .../aots/tests/gsub_chaining3_next_glyph.tests     |   1 +
+ .../data/aots/tests/gsub_chaining3_simple.tests    |  11 +
+ .../aots/tests/gsub_chaining3_successive.tests     |   1 +
+ .../data/aots/tests/gsub_context1_boundary.tests   |   2 +
+ .../data/aots/tests/gsub_context1_expansion.tests  |   1 +
+ .../data/aots/tests/gsub_context1_lookupflag.tests |   2 +
+ .../tests/gsub_context1_multiple_subrules.tests    |   2 +
+ .../data/aots/tests/gsub_context1_next_glyph.tests |   1 +
+ .../data/aots/tests/gsub_context1_simple.tests     |   3 +
+ .../data/aots/tests/gsub_context1_successive.tests |   1 +
+ .../data/aots/tests/gsub_context2_boundary.tests   |   2 +
+ .../data/aots/tests/gsub_context2_classes.tests    |   2 +
+ .../data/aots/tests/gsub_context2_expansion.tests  |   1 +
+ .../data/aots/tests/gsub_context2_lookupflag.tests |   2 +
+ .../tests/gsub_context2_multiple_subrules.tests    |   2 +
+ .../data/aots/tests/gsub_context2_next_glyph.tests |   1 +
+ .../data/aots/tests/gsub_context2_simple.tests     |   3 +
+ .../data/aots/tests/gsub_context2_successive.tests |   1 +
+ .../data/aots/tests/gsub_context3_boundary.tests   |   2 +
+ .../data/aots/tests/gsub_context3_lookupflag.tests |   2 +
+ .../data/aots/tests/gsub_context3_next_glyph.tests |   1 +
+ .../data/aots/tests/gsub_context3_simple.tests     |   2 +
+ .../data/aots/tests/gsub_context3_successive.tests |   1 +
+ .../data/aots/tests/lookupflag_ignore_attach.tests |   5 +
+ .../data/aots/tests/lookupflag_ignore_base.tests   |   2 +
+ .../aots/tests/lookupflag_ignore_combination.tests |   3 +
+ .../aots/tests/lookupflag_ignore_ligatures.tests   |   3 +
+ .../data/aots/tests/lookupflag_ignore_marks.tests  |   1 +
+ test/shaping/run-tests.py                          |   9 +-
+ 332 files changed, 815 insertions(+), 3 deletions(-)
+
+commit ae96c98dfaef3a789227ffecd40b92518dface8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:25:10 2018 -0500
+
+    [color] Use SortedUnsizedArrayOf<>
+
+ src/hb-ot-color-colr-table.hh | 16 ++--------------
+ 1 file changed, 2 insertions(+), 14 deletions(-)
+
+commit 4a3b20738fca3231e5d9a36adba333b5bce05f4a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:17:59 2018 -0500
+
+    [trak] Coment
+
+ src/hb-aat-layout-trak-table.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 918b1ee54d43eb493c9226bff7677ed8ec07934b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:09:17 2018 -0500
+
+    [arrays] Add not_found to reference bsearch as well
+
+ src/hb-open-type.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit d77a098b735cf14aa601feab5bdb9f4e474c794f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 10:06:13 2018 -0500
+
+    [arrays] Improve bfind() interface
+
+    Much more useful now. :)
+
+ src/hb-dsalgs.hh           | 29 +++++++++++++++++++++++++----
+ src/hb-open-file.hh        |  9 +--------
+ src/hb-open-type.hh        | 12 ++++++++----
+ src/hb-ot-layout-common.hh | 10 ++--------
+ src/hb-set.hh              |  6 +++---
+ src/hb-vector.hh           |  6 ++++--
+ 6 files changed, 43 insertions(+), 29 deletions(-)
+
+commit 1204a247a5d9a4da39675d3da85d4fd3268a5b66
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 09:49:21 2018 -0500
+
+    [fuzzing] Add tests for previous commit
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11526
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11522
+
+ ...zz-testcase-minimized-hb-shape-fuzzer-5634620935110656 | Bin 0 ->
+ 41 bytes
+ ...zz-testcase-minimized-hb-shape-fuzzer-5716208469409792 | Bin 0 ->
+ 243 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 8dcc1913a1670ede7b124f7b5b775d7ab8791386
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 09:47:45 2018 -0500
+
+    [kerx/morx] Make sure object length is sanitized before accessing it
+
+ src/hb-aat-layout-kerx-table.hh | 5 +++++
+ src/hb-aat-layout-morx-table.hh | 5 +++++
+ 2 files changed, 10 insertions(+)
+
+commit 70d80c90fe2f4eca66bec3e1d313bbf7e4d0ab65
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:59:50 2018 -0500
+
+    [arrays] Port ArrayOf.qsort() and hb_vector_t.qsort() to hb_array_t
+
+ src/hb-dsalgs.hh    | 14 ++++++++++++--
+ src/hb-open-type.hh | 14 ++++++++++++--
+ 2 files changed, 24 insertions(+), 4 deletions(-)
+
+commit 073d837aa2394d29dda72679802d583c559c3c5b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:48:48 2018 -0500
+
+    [arrays] Port ArrayOf.qsort() to hb_array_t's
+
+ src/hb-open-type.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit ad5c871d801b481f95dd32c8b65ecc70def597be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:47:49 2018 -0500
+
+    [arrays] Add copy-constructor to hb_array_t and hb_sorted_array_t
+
+ src/hb-dsalgs.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 61de55bf496c1edb120e4d096140eb1125552bbe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:45:58 2018 -0500
+
+    [arrays] Port hb_vector_t.qsort() to hb_array_t's
+
+ src/hb-dsalgs.hh | 16 +++++++++++++---
+ src/hb-vector.hh | 10 ++--------
+ 2 files changed, 15 insertions(+), 11 deletions(-)
+
+commit e3face8e791d677f94154e8a7f3d787d0d69a02f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:42:17 2018 -0500
+
+    [arrays] Remove one flavor of hb_vector_t.qsort()
+
+ src/hb-vector.hh | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+commit 7c1600dcd9813ca560ecccc5c54877a5750caf4e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:37:11 2018 -0500
+
+    [arrays] Add (unused) SortedUnsizedArrayOf<>
+
+ src/hb-open-type.hh | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+commit e700392f5cbf366f1e03dc7e7b1a2eb6c3027b92
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:31:00 2018 -0500
+
+    [arrays] Port SortedArrayOf.bsearch/bfind to hb_sorted_array_t's
+
+ src/hb-dsalgs.hh    |  9 +++------
+ src/hb-open-type.hh | 50
+ ++++++++++----------------------------------------
+ src/hb-vector.hh    | 35 ++++++++++-------------------------
+ 3 files changed, 23 insertions(+), 71 deletions(-)
+
+commit e604306f2829804e9016966c1378166253b19d29
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:24:48 2018 -0500
+
+    [arrays] Port hb_vector_t.bsearch/bfind to (new) hb_sorted_array_t's
+
+ src/hb-dsalgs.hh    | 63
+ +++++++++++++++++++++++++++++++++++++++++++++++++----
+ src/hb-open-type.hh | 12 ++++++----
+ src/hb-vector.hh    | 57 +++++++++++++++++++-----------------------------
+ 3 files changed, 89 insertions(+), 43 deletions(-)
+
+commit 268eca24921e85eda98f4f0cce05d40c7235ba62
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:11:12 2018 -0500
+
+    [arrays] Port (unused) ArrayOf.lsearch() to hb_array_t's
+
+ src/hb-open-type.hh | 12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+commit 830856ba6b9454bf507e00416f9d45e9975fb7dc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:09:28 2018 -0500
+
+    [arrays] Port hb_vector_t.lsearch() to hb_array_t's
+
+ src/hb-dsalgs.hh | 26 +++++++++++++++++++++++---
+ src/hb-vector.hh | 16 ++++------------
+ 2 files changed, 27 insertions(+), 15 deletions(-)
+
+commit 96cf0889804b7d72a96274b25641bb18f7dd2e1e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 01:07:15 2018 -0500
+
+    [arrays] More
+
+ src/hb-face.cc   | 6 +++---
+ src/hb-vector.hh | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 3e26c8d2b10fc08642c25c7f13aef68b0b1008f6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:58:44 2018 -0500
+
+    [arrays] Update ArrayOf.lsearch()
+
+    Currently unused apparently
+
+ src/hb-open-type.hh | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+commit 22e1857b01c71714245ddca05cb3fa0127bf7da2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:53:19 2018 -0500
+
+    [arrays] Change argument type of cmp called by hb_vector_t.bsearch()
+
+    Towards consolidating all array bsearch/...
+
+ src/hb-aat-map.hh | 4 ++--
+ src/hb-ot-map.hh  | 4 ++--
+ src/hb-set.hh     | 2 +-
+ src/hb-vector.hh  | 4 ++--
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 5fdf7b724eb3cb5ac60cd7f90d3250877ad7ca06
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Thu Nov 15 17:40:21 2018 -0600
+
+    Usermanual: clusters chapter; add brief grapheme definition and
+    clarify monotonous cluster handling.
+
+ docs/usermanual-clusters.xml | 56
+ ++++++++++++++++++++++++++++++--------------
+ 1 file changed, 39 insertions(+), 17 deletions(-)
+
+commit 939220e57da613e090d247aa1af2396c28370af4
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Thu Nov 15 15:47:03 2018 -0600
+
+    Usermanual: clusters chapter, minor updates.
+
+ docs/usermanual-clusters.xml | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+commit 53ac46e974cf0ee8720b40ef394714eb97ff53b9
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Mon Nov 12 12:17:06 2018 -0600
+
+    Usermanual: expand clusters chapter.
+
+ docs/usermanual-clusters.xml | 743
+ +++++++++++++++++++++++++++----------------
+ 1 file changed, 473 insertions(+), 270 deletions(-)
+
+commit 30cb45b3eaacda15cc45435815cae3fd50e87557
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:35:31 2018 -0500
+
+    Change ArrayOf.bsearch() return semantics
+
+    Towards consolidating all array bsearch/...
+
+ src/hb-aat-layout-kerx-table.hh | 16 +++-------------
+ src/hb-open-file.hh             | 12 ++++++++----
+ src/hb-open-type.hh             | 42
+ ++++++++++++++++++++++++++++++++---------
+ src/hb-ot-cmap-table.hh         | 30 ++++++++++++-----------------
+ src/hb-ot-color-svg-table.hh    |  3 +--
+ src/hb-ot-layout-common.hh      | 29 +++++++++++-----------------
+ src/hb-ot-vorg-table.hh         |  9 ++++-----
+ src/hb-vector.hh                | 14 +++++++++-----
+ 8 files changed, 81 insertions(+), 74 deletions(-)
+
+commit 5cd9546ba73d9f8c8b7b8db0960d657c50b70f64
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:38:36 2018 -0500
+
+    Minor
+
+ src/hb-ot-layout-common.hh | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+commit fd94e729cb50f2b6bd83b80cbf400e10ac633a1c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:45:55 2018 -0500
+
+    Whitespace
+
+ src/hb-ot-layout-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit bb2a2065080a3099eb0dc82d1df0891ad2601316
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:31:40 2018 -0500
+
+    Assert that item-type of arrays have static size
+
+ src/hb-dsalgs.hh    | 2 ++
+ src/hb-open-type.hh | 4 ++++
+ src/hb-vector.hh    | 2 ++
+ 3 files changed, 8 insertions(+)
+
+commit 690d9eb83d3421b397b0cb824cd768d6d73cbf12
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:29:22 2018 -0500
+
+    [vector] Rename
+
+ src/hb-vector.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit ba38378fd4374f3d44bdc9aa0de902401b60b13d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:27:57 2018 -0500
+
+    [aat] Minor
+
+ src/hb-aat-layout-common.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 39b9d63b014380d421cc9b94a49dd411c7a5aabf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:25:40 2018 -0500
+
+    Add hb_static_size(T)
+
+ src/hb-null.hh | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+commit f99abcc37990a478189dda691d1fdac7b9d51386
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 24 00:22:21 2018 -0500
+
+    Add template-function convenience macros
+
+ src/hb-atomic.hh |  2 +-
+ src/hb-blob.hh   |  4 ++--
+ src/hb-common.cc |  2 +-
+ src/hb-ft.cc     |  2 +-
+ src/hb-null.hh   | 11 ++++++-----
+ src/hb.hh        |  3 +++
+ 6 files changed, 14 insertions(+), 10 deletions(-)
+
+commit ec83b2228e0bbb6df7e7b94dad49db32b041af4a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 19:58:49 2018 -0500
+
+    Add null bytes for CmapSubtableLongGroup
+
+ src/hb-ot-cmap-table.hh | 1 +
+ src/hb-static.cc        | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit e2ffb33a534a427c760dae53d0469eeced4343ba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 16:24:28 2018 -0500
+
+    Remove lsearch for small TableDirectorys
+
+ src/hb-open-file.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 04f7e5536924e7f277d72b8cb9d878239877c331
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 16:07:43 2018 -0500
+
+    [arrays] Add as_array() to hb_vector_t<>
+
+ src/hb-vector.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit c514f65181390ab98b0f738632f71cda31e46b68
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 16:04:56 2018 -0500
+
+    [arrays] Add as_array() to ArrayOf<>
+
+ src/hb-open-type.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 9552f4ef0da0b7e1fb28cb2738b865888e7941d9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 15:24:17 2018 -0500
+
+    [kern] Don't enforce length of last subtable
+
+ src/hb-aat-layout-kerx-table.hh | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+commit 992b7128656e72f935089dc2e12c2d2a25511886
+Merge: c9cc96c0 018ba46e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 13:49:34 2018 -0500
+
+    Merge pull request #1407 from harfbuzz/at-sign
+
+    Don't canonicalize '@' to '-' in language tags
+
+commit 018ba46e4d003a5dd0f6d2d899226129c4ef0c60
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Nov 23 13:21:22 2018 -0500
+
+    Don't canonicalize '@' to '-' in language tags
+
+    Fixes #1406.
+
+ src/hb-common.cc       | 2 +-
+ test/api/test-ot-tag.c | 3 +++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit c9cc96c0cfbbb87b9292e413d500a454182be9f4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 23 19:58:56 2018 +0330
+
+    [aat] Update expectation
+
+ test/shaping/data/in-house/tests/macos-10.12.tests | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 748962264a9f098b32b9cb3fe4d18c786907a184
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 11:10:17 2018 -0500
+
+    [aat] Disable mark advance zeroing if kern table has state-machines
+
+    Geeza Pro for example, relies on that for fancy mark positioning.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1405
+
+ src/hb-aat-layout-kerx-table.hh | 15 +++++++++++++++
+ src/hb-ot-kern-table.hh         |  9 +++++++++
+ src/hb-ot-layout.cc             |  6 ++++++
+ src/hb-ot-layout.hh             |  3 +++
+ src/hb-ot-shape.cc              |  4 +++-
+ 5 files changed, 36 insertions(+), 1 deletion(-)
+
+commit 3d2b98ef14af29acd74f01647bef60cd410825fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 23 10:45:44 2018 -0500
+
+    Minor
+
+ src/hb.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 341851efe158599a34d241a97593058a4333852e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Nov 23 15:40:05 2018 +0330
+
+    [aat] Add macOS specific tests (#1404)
+
+ .circleci/config.yml                               | 46
+ ++++++++++++++--------
+ test/shaping/CMakeLists.txt                        |  2 +
+ test/shaping/data/in-house/Makefile.sources        |  1 +
+ test/shaping/data/in-house/tests/macos-10.12.tests | 10 +++++
+ test/shaping/run-tests.py                          | 38
+ ++++++++++++++----
+ 5 files changed, 73 insertions(+), 24 deletions(-)
+
+commit 22798e93c414a2655c757a6e41b300f67e04a9a3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:47:51 2018 -0500
+
+    [use] Minor clarification
+
+ src/hb-ot-shape-complex-use.cc | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+commit a2d6c1075a5595a08ef09357293919d9df8eb64a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:40:57 2018 -0500
+
+    Minor tweak to FLAG64
+
+ src/hb.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 8280459e74cff2dec3de012abd309cda9578b759
+Merge: e4a4555d 3c7792ca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:39:12 2018 -0500
+
+    Merge pull request #1291 from harfbuzz/use-reordering
+
+    [use] Fix reordering
+
+commit e4a4555d1e40dacdf72452805e9e6b6109627d63
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:17:49 2018 -0500
+
+    [cmap] Move code around
+
+ src/hb-ot-cmap-table.hh | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+commit 758c9d68e2143493978d8ac8391f4af2a2abc26a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:16:12 2018 -0500
+
+    [morx/kerx] Limit range to subtable when sanitizing
+
+ src/hb-aat-layout-kerx-table.hh | 2 ++
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ 2 files changed, 4 insertions(+)
+
+commit a9fe787a11fc391d9a43a4ea19e6eb1c474199bd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:12:36 2018 -0500
+
+    [sanitizer] Add reset_object(), make set_object() do bounds-check
+
+    Affects morx/kerx run-time only currently.  Will adjust their
+    sanitize next.
+
+ src/hb-aat-layout-kerx-table.hh |  1 +
+ src/hb-aat-layout-morx-table.hh |  1 +
+ src/hb-machinery.hh             | 30 +++++++++++++++++++-----------
+ 3 files changed, 21 insertions(+), 11 deletions(-)
+
+commit 2c8188bf599e351a4e0804d74612f9643b3d2443
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 22:02:19 2018 -0500
+
+    [kerx] Make sure subtables are non-zero-length
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11400
+
+ src/hb-aat-layout-kerx-table.hh                          |   1 +
+ src/hb-aat-layout-morx-table.hh                          |   2 +-
+ ...z-testcase-minimized-hb-shape-fuzzer-5722888989048832 | Bin 0 ->
+ 3608 bytes
+ 3 files changed, 2 insertions(+), 1 deletion(-)
+
+commit a9e0bdc35dfcbead7d4b6fa249d60ebedd7d43ca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 21:30:04 2018 -0500
+
+    [GSUB] Don't flush glyphset during recursion in closure()
+
+    See comment.
+
+    Supercedes https://github.com/harfbuzz/harfbuzz/pull/1401
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11366
+
+ src/hb-ot-layout-gsub-table.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 8982830d3ec54f50cc951de9569520fafc735e75
+Author: Garret Rieger <grieger@google.com>
+Date:   Mon Nov 19 13:00:24 2018 -0800
+
+    [subset] add fuzzer testcase.
+
+ ...z-testcase-minimized-hb-subset-fuzzer-5067936541179904 | Bin 0 ->
+ 172 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit d0e81b2cc85d09d01905c5fc5b3382c25eaa3bb3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 21:20:39 2018 -0500
+
+    [set] Rename
+
+ src/hb-set.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit e866910579e9cdc5b1ffa2e401fd0c056d44ca6a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 18:07:59 2018 -0500
+
+    Enforce requiring null_size even if min_size is 0
+
+    This concludes null-size enforcement changes
+
+ src/hb-null.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4d4fd64ff47da04a7008d410c92e8fb4ad970781
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 18:07:36 2018 -0500
+
+    Allow non-nullable OffsetTo<> to non-Null'able objects
+
+ src/hb-open-type.hh | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+commit fa9f585ec53bc7145d3bed1a4bd756d64dae1e55
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 17:56:51 2018 -0500
+
+    [glyf] Don't mark structs UNBOUNDED
+
+    See comments.
+
+ src/hb-ot-glyf-table.hh | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit f47a60a7543dbaf41086c25a1a22ae518d8b92a9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 17:53:29 2018 -0500
+
+    Mark UnsizedArrayOf<> as UNBOUNDED
+
+    Since min_size is 0, Null() still accepts this type.
+
+ src/hb-open-type.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 199a0f7b41b691e371487fd569c0d0146da3c3f3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 17:31:07 2018 -0500
+
+    [ot-shape] Simplify logic
+
+ src/hb-ot-shape.cc | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 014e4980ed9c8c473001abdb3a44121eb73fd50d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 16:21:49 2018 -0500
+
+    Move
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 62890dee18b88865a2014fb6a1322c1c9218bd49
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 16:20:29 2018 -0500
+
+    [aat] Zero mark advances if decided so even if there's cross-kerning
+
+    Cross-kerning can only take care of positioning vertically.
+    It doesn't
+    adjust mark advance...
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a201fa74cd67f36a402a5c8093889c9d793e9fd5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 15:52:29 2018 -0500
+
+    [aat] Tweak fallback positioning logic when applying morx
+
+    Such that for Indic-like scripts (eg. Khmer), we don't do any
+    fallback mark
+    advance-zeroing / positioning, but we do for Latin, etc.  Reuses
+    preferences
+    of our script-specific OpenType shapers for those.
+
+    Fixes regression: https://github.com/harfbuzz/harfbuzz/issues/1393
+    Which means, fixes again:
+    https://github.com/harfbuzz/harfbuzz/issues/1264
+    While not regressing: https://github.com/harfbuzz/harfbuzz/issues/1357
+
+ src/hb-ot-shape.cc | 38 +++++++++++++++++++++++---------------
+ src/hb-ot-shape.hh |  3 +++
+ 2 files changed, 26 insertions(+), 15 deletions(-)
+
+commit fa0bd8964d110c168a918bc331dcd350c3fed8c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 14:46:39 2018 -0500
+
+    [myanmar] Minor move
+
+ src/hb-ot-shape-complex.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 7dc561984bdb1f29f09ae0793195b5fbf772522b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 14:45:46 2018 -0500
+
+    [myanmar] If there's no GSUB table, pick myanmar shaper
+
+    Needed for morx+kern mark-zeroing interaction.  All other scripts
+    work this way.
+
+ src/hb-ot-shape-complex.hh | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+commit 25f52f58c20715cc0dee2dd2885669078a128b08
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 14:41:01 2018 -0500
+
+    [myanmar] Remove myanmar_old shaper
+
+    Over time it has become the same as default shaper.  So, remove.
+
+ src/hb-ot-shape-complex-myanmar.cc | 21 ---------------------
+ src/hb-ot-shape-complex.hh         |  4 +---
+ 2 files changed, 1 insertion(+), 24 deletions(-)
+
+commit eeed802b1d0f932c61a088d3e0156ae70645b9e2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:53:36 2018 -0500
+
+    Fix spurious gcc warnings
+
+    ../../src/hb-null.hh:53:39: warning: enum constant in boolean context
+    [-Wint-in-bool-context]
+
+ src/hb-null.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b96ecb9971a9ad089a631d0139f05ae9d880fc55
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:49:12 2018 -0500
+
+    More
+
+    This makes more of the gcc spurious warning:
+
+    ../../src/hb-null.hh:53:39: warning: enum constant in boolean context
+    [-Wint-in-bool-context]
+
+    But not going to let that defeat correct code.  Type to switch
+    to clang
+    as my main compiler...
+
+ src/hb-blob.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2737aa81e5aee721e868bf0c72f19c0245c721fe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:44:27 2018 -0500
+
+    Fix up recent change
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1300
+
+ src/hb-null.hh          | 12 +++++++++---
+ src/hb-open-type.hh     |  5 -----
+ src/hb-ot-glyf-table.hh |  4 ++--
+ 3 files changed, 11 insertions(+), 10 deletions(-)
+
+commit fffea5aff7a631eedd13c38c1fb7ea4f5f950930
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:25:34 2018 -0500
+
+    Minor
+
+ src/hb-open-type.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 209b58ef731f102b92179ed76551e2fd6b5ed075
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:22:33 2018 -0500
+
+    Minor
+
+ src/hb-ot-kern-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3b9fd176e83bbebc4d0b5fc967c15b08fdef7015
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:18:55 2018 -0500
+
+    Disallow taking Null() of unbounded structs
+
+    Not sure I've marked all such structs.  To be done as we discover.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1300
+
+ src/hb-aat-layout-common.hh |  2 +-
+ src/hb-machinery.hh         |  4 ++++
+ src/hb-ot-kern-table.hh     |  2 +-
+ src/hb-ot-var-fvar-table.hh | 31 ++++++++++++++++---------------
+ 4 files changed, 22 insertions(+), 17 deletions(-)
+
+commit f2b91d6510face95008151bb0d25837723536f9f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:10:22 2018 -0500
+
+    Use Type::null_size for our structs in Null(), sizeof() for other
+    types
+
+ src/hb-null.hh | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+commit 7dd945a8764cbbf76f686fd9387918b63f7d2fb4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 01:05:02 2018 -0500
+
+    One more time..
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d062ad10de6c63d94676660b76526a160cf4299e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 00:39:14 2018 -0500
+
+    Fix bots happy again, hopefully
+
+    So, our fallback static_assert cannot be had more than once per line
+    of source.
+
+ src/hb-machinery.hh | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+commit fb10c021c8a32f8dc054f008caf86af82667e109
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 22 00:21:49 2018 -0500
+
+    Revert alignof() == 1 check
+
+    Bots not happy with using "this" inside assertion...
+
+    This reverts 2656644887e77a9d814bb12374af3c26b42fd935
+
+ src/hb-machinery.hh | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+commit 8d778877b88155dec1808a994416ead0b3d98ae7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:46:09 2018 -0500
+
+    ..
+
+ src/hb-machinery.hh | 8 ++++++--
+ src/hb-null.hh      | 4 ++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+commit 8cfeed99486e87c3217dc141bc24b7768a460f32
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:42:31 2018 -0500
+
+    Minor
+
+ src/hb-machinery.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e5d954a2fb0c390ea67e83763e3c3a47caa2eb50
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:30:50 2018 -0500
+
+    Minor
+
+ src/hb-machinery.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e987059c618e03d2346c31ed64429d67ce0e367a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:25:06 2018 -0500
+
+    Minor
+
+ src/hb-machinery.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit a2b6d308a40d737f54a79f00bc7ace226bad5aaf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:23:49 2018 -0500
+
+    Remove DEFINE_SIZE_ARRAY2
+
+ src/hb-machinery.hh        | 6 ------
+ src/hb-ot-layout-common.hh | 8 ++++----
+ src/hb-ot-post-table.hh    | 6 +++---
+ 3 files changed, 7 insertions(+), 13 deletions(-)
+
+commit 2656644887e77a9d814bb12374af3c26b42fd935
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:23:21 2018 -0500
+
+    Check alignof() structs are 1
+
+ src/hb-machinery.hh | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+commit 6321fdf7040ce48e3de8d34fdcc57caa6433cb66
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 23:19:00 2018 -0500
+
+    Whitespace
+
+ src/hb-machinery.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit f961c1eb88af0d178e5d3431b9d57bdf79669488
+Merge: ecdceea8 264439c6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 17:27:27 2018 -0500
+
+    Merge pull request #1400 from harfbuzz/sharada-sandhi-mark
+
+    Test U+111C9 SHARADA SANDHI MARK
+
+commit 264439c6c308ac5f01c4ba4faf64daa2d642236a
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Wed Nov 21 16:33:45 2018 -0500
+
+    Test U+111C9 SHARADA SANDHI MARK
+
+ .../fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf    | Bin 0 ->
+ 968 bytes
+ test/shaping/data/in-house/tests/use-syllable.tests       |   1 +
+ 2 files changed, 1 insertion(+)
+
+commit ecdceea861952be003e1d435aa3282a4e3e200a9
+Merge: b89c7fd3 b3d5b0a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 16:12:32 2018 -0500
+
+    Merge pull request #1399 from harfbuzz/sharada-sandhi-mark
+
+    Fix USE categories for U+111C9 SHARADA SANDHI MARK
+
+commit b89c7fd3dc505a958dd4b6acec0e0f8e57224fd8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 21 12:32:48 2018 -0500
+
+    Allow defining HB_USE_ATEXIT to 0
+
+    That's better use of that value than requiring extra macro
+    HB_NO_ATEXIT
+
+ src/hb-common.cc    | 10 +++++-----
+ src/hb-ft.cc        | 12 ++++++------
+ src/hb-glib.cc      |  6 +++---
+ src/hb-icu.cc       |  6 +++---
+ src/hb-ot-font.cc   |  6 +++---
+ src/hb-shape.cc     |  6 +++---
+ src/hb-shaper.cc    |  6 +++---
+ src/hb-ucdn.cc      |  6 +++---
+ src/hb-uniscribe.cc |  4 ++--
+ src/hb.hh           |  5 ++++-
+ 10 files changed, 35 insertions(+), 32 deletions(-)
+
+commit b3d5b0a5d92115ca672b8103999ab7ac88e39a4a
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Wed Nov 21 11:35:44 2018 -0500
+
+    Fix USE categories for U+111C9 SHARADA SANDHI MARK
+
+ src/gen-use-table.py                 | 7 ++++++-
+ src/hb-ot-shape-complex-use-table.cc | 2 +-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+commit f48bb9a3939067f24a81007e642caaac77cc7167
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 20:40:55 2018 -0500
+
+    [var] Deprecated axis enumeration API and add new version
+
+    New version has axis flags.
+
+    New API:
+    +hb_ot_var_axis_info_t
+    +hb_ot_var_find_axis_info()
+    +hb_ot_var_get_axis_infos()
+
+    Deprecated API:
+    -HB_OT_VAR_NO_AXIS_INDEX
+    -hb_ot_var_axis_t
+    -hb_ot_var_find_axis()
+    -hb_ot_var_get_axes()
+
+ docs/harfbuzz-sections.txt  |  14 +++---
+ src/hb-deprecated.h         |  37 +++++++++++++++
+ src/hb-ot-var-fvar-table.hh | 112
+ ++++++++++++++++++++++++++++++++------------
+ src/hb-ot-var.cc            |  43 ++++++++++++++---
+ src/hb-ot-var.h             |  61 ++++++++++++------------
+ test/api/test-ot-face.c     |   2 +-
+ 6 files changed, 192 insertions(+), 77 deletions(-)
+
+commit b2d803cef6974519d5892af2c9efeb8dfba87618
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 11:42:25 2018 -0500
+
+    Remove newly-added -hb_ot_var_axis_get_flags()
+
+ src/hb-ot-var-fvar-table.hh |  6 ------
+ src/hb-ot-var.cc            | 12 ------------
+ src/hb-ot-var.h             |  4 ----
+ 3 files changed, 22 deletions(-)
+
+commit 736897d7a1410fd281fbcedc084b85bf4ba1410c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 11:40:43 2018 -0500
+
+    [var] Make sure hb_ot_var_axis_flags_t is int-sized
+
+ src/hb-ot-var.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit eab5d15f6156e771cb606b760dd170b96c5cd398
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 11:33:33 2018 -0500
+
+    [var] Move code
+
+ src/hb-ot-var.h | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+commit 1ecbf4d3e3de7edc86651c6f805788747d6d89af
+Merge: 515f1a16 064f703c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Nov 20 17:19:05 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit 064f703c7ac5a28803a8221720e922ea6dbd2505
+Merge: be1828da 82951182
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 16:29:30 2018 -0500
+
+    Merge pull request #1397 from harfbuzz/small-emoji-table
+
+    Shrink the emoji table by merging adjacent ranges
+
+commit 82951182799772a642d32195dd87e6f0c116f545
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Tue Nov 20 15:41:45 2018 -0500
+
+    Shrink the emoji table by merging adjacent ranges
+
+ src/gen-emoji-table.py        |  13 +--
+ src/hb-unicode-emoji-table.hh | 189
+ ++++--------------------------------------
+ 2 files changed, 23 insertions(+), 179 deletions(-)
+
+commit be1828daaa1e1a72d971aed8d34fff54688d0f41
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 11:16:23 2018 -0500
+
+    [var] Fix type of coords returned
+
+    Ouch.  Wonder how none of the bots caught the float->int truncation.
+
+ src/hb-ot-var-fvar-table.hh | 2 +-
+ src/hb-ot-var.cc            | 2 +-
+ src/hb-ot-var.h             | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 8f3ee17ae468950a34439785d2e6ac4182efb65c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 01:38:23 2018 -0500
+
+    [travis] Update Coverity token
+
+ .travis.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f9552362986efd0973b2637d21b787edbc8479f2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 01:21:36 2018 -0500
+
+    Add codecov.io badge
+
+ README | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 831ba74382e35f110006539f22bebce4d57c8502
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 01:16:08 2018 -0500
+
+    Fix Codacy "issues"
+
+ src/test-name-table.cc  |  2 +-
+ src/test-ot-color.cc    | 14 +++++++-------
+ test/api/test-buffer.c  |  5 +++--
+ test/api/test-object.c  |  2 +-
+ test/api/test-ot-name.c |  2 +-
+ 5 files changed, 13 insertions(+), 12 deletions(-)
+
+commit c49e43c1ffee0e9664da6202ace493d932b725a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 01:06:50 2018 -0500
+
+    [travis] Another push for codecov.io after setting token
+
+ .travis.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 96b24c5124a085b7601215360eed847ce5302699
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 20 01:03:42 2018 -0500
+
+    [travis] Add codecov.io
+
+ .travis.yml | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 3c7792ca326abfb989285f794d6ee71ad9f6bf89
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Sat Oct 20 15:02:26 2018 -0400
+
+    [use] Fix reordering
+
+    Fixes #1235.
+
+ src/hb-ot-shape-complex-use.cc                     |  48
+ ++++++++++++++-------
+ src/hb.hh                                          |   2 +
+ .../4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf   | Bin 0 -> 1824 bytes
+ test/shaping/data/in-house/tests/use.tests         |   3 ++
+ 4 files changed, 38 insertions(+), 15 deletions(-)
+
+commit 587d49fc657c10c8a20f2409a04d72bf80bb361e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 14:27:19 2018 -0500
+
+    [fvar] Add named-instance API
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1241
+
+ docs/harfbuzz-sections.txt  |  4 ++++
+ src/hb-ot-var-fvar-table.hh | 55
+ ++++++++++++++++++++++++++++++++++++++++++---
+ src/hb-ot-var.cc            | 33 +++++++++++++++++++++++++++
+ src/hb-ot-var.h             | 32 ++++++++++++++++++++++++++
+ 4 files changed, 121 insertions(+), 3 deletions(-)
+
+commit 46c0da820fc313bad8afaf019d2cd9065fa5f514
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 13:32:48 2018 -0500
+
+    Fix build
+
+ src/hb-dsalgs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 56c9238d3da8c034336cf80ba37e03e33c493718
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 13:09:53 2018 -0500
+
+    [fvar] Rewrite sanitize
+
+ src/hb-ot-var-fvar-table.hh | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit 4a6a692e3ea4fab632a0162c6d513dc151054d8f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 13:04:43 2018 -0500
+
+    [fvar] Use hb_array_t for axes
+
+ src/hb-dsalgs.hh            |  6 ++++++
+ src/hb-ot-var-fvar-table.hh | 14 ++++----------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit e0097396010c40cf62641cd12ceb12dd5d79c9c7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 12:53:53 2018 -0500
+
+    [fvar] Minor
+
+ src/hb-ot-var-fvar-table.hh | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+commit 1a2eb108b857de9c5e84cc5de0c12c7657e04498
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 12:36:56 2018 -0500
+
+    [ot-var] Add hb_ot_var_axis_get_flags()
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1241
+
+    New API:
+    +hb_ot_var_axis_flags_t
+    +hb_ot_var_axis_get_flags
+
+ docs/harfbuzz-sections.txt  |  2 ++
+ src/hb-buffer.h             |  2 ++
+ src/hb-ot-var-fvar-table.hh |  9 +++++++++
+ src/hb-ot-var.cc            | 12 ++++++++++++
+ src/hb-ot-var.h             | 13 +++++++++++++
+ 5 files changed, 38 insertions(+)
+
+commit bd6b2ba1d3910cc259db7abeb6c9bd7ed9494857
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 11:34:56 2018 -0500
+
+    [ot-var] Add flags
+
+    Unfortunate that we don't have room in hb_ot_var_axis_t to expose
+    flags :(.
+
+ src/hb-ot-var-fvar-table.hh | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+commit c076c7b85ce4d069ae8b2b04143aca4c4f052ae9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 19 11:30:40 2018 -0500
+
+    [ot-var] Use hb_ot_name_id_t
+
+ src/hb-ot-var.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 515f1a16140f78c9ec379854851f77a1b44af145
+Merge: a6da9b94 e3a1a835
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 16 17:38:47 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit a6da9b9415bae43c58f12a8e43b77ba31dd432a6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 16 17:29:03 2018 -0800
+
+    fixed Charset format selection
+
+ src/hb-subset-cff1.cc | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit e3a1a8350a6a7933b0a100194985f4425ab9de19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 16:53:25 2018 -0800
+
+    2.1.3
+
+ NEWS             | 6 ++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+commit 9714e114b88893bd962b1bcf36382bdacbc4866c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 16:52:42 2018 -0800
+
+    Fix recent commits
+
+ src/hb-open-type.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0328a1ce41611ed981d41384ae5727479699f3a0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 16:48:28 2018 -0800
+
+    Revert b4c61130324455bfd42095b01fa14ac901e441f1
+
+    Was causing more trouble than it solved.  We use unsigned for
+    indexing,
+    and it's not helpful to allow that wrapping to negative integers on
+    32bit machines.  The only way we could work around it would have been
+    by accepting int64_t arg, but that's overkill.
+
+    Ignore the MSVC 2008 build issue.  We don't support that compiler.
+
+ src/hb-open-type.hh | 17 ++++-------------
+ 1 file changed, 4 insertions(+), 13 deletions(-)
+
+commit 52f61cdb87b67ef42a25288d8624170d0b6d3a25
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 16:41:59 2018 -0800
+
+    Detect over/under-flow in UnsizedArray::operator[]
+
+    Was causing bad substitutions in mort table because of
+    WordOffsetToIndex()
+    producing negative numbers that were cast to unsigned int and
+    returned as
+    large numbers (which was desirable, so they would be rejected),
+    but then
+    they were cast to int when passed to this operator and acting as small
+    negative integers, which was bad...
+
+    Detect overflow.  Ouch, however, now I see this still fails on 32-bit.
+    Guess I'm going to revert an earlier change.
+
+ src/hb-open-type.hh | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+commit 6910ff03e66f5f4c9eb5592262d414ef7d91df04
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 16:11:02 2018 -0800
+
+    [aat] Fix mort shaping
+
+    Ouch!
+
+ src/hb-aat-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fdb29ab2b0058c9813f9fc44c83dd9048db92d16
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 15:38:11 2018 -0800
+
+    2.1.2
+
+ NEWS             | 13 ++++++++++++-
+ configure.ac     |  2 +-
+ src/hb-version.h |  4 ++--
+ 3 files changed, 15 insertions(+), 4 deletions(-)
+
+commit cff4c6087fdb667a40f54f20ca3c49251bf076de
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 15:04:41 2018 -0800
+
+    Fix vertical fallback space sign
+
+    Ouch!
+
+    Follow-up to cf203af8a33591c163b63dbdf0fd341bc4606190
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1343
+
+ src/hb-ot-shape-fallback.cc                   |  8 ++++----
+ test/shaping/data/in-house/tests/spaces.tests | 22 +++++++++++-----------
+ 2 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 7a97f7074052a5d746af29f0743abd20682b09a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 14:46:40 2018 -0800
+
+    Don't apply GPOS if applying morx
+
+    That's what Apple does, and it wouldn't degrade our OpenType
+    performance.
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1348
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit eafd515639497098436ecf4c7b836e231bced323
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 14:45:56 2018 -0800
+
+    Prefer morx table if GSUB is empty (no scripts)
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1348
+
+ src/hb-ot-shape.cc | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit aa06574823e27c4dbb378d2467a3e6f6f36af9fe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 14:31:05 2018 -0800
+
+    Minor
+
+ src/hb-aat-layout-trak-table.hh | 2 +-
+ src/hb-ot-layout-gdef-table.hh  | 2 +-
+ src/hb-ot-layout-gsubgpos.hh    | 2 +-
+ src/hb-ot-math-table.hh         | 2 +-
+ src/hb-ot-var-fvar-table.hh     | 2 +-
+ 5 files changed, 5 insertions(+), 5 deletions(-)
+
+commit b6903bd6c4b0c792c821e37a8e223088ae40e5fa
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 16 13:46:58 2018 -0800
+
+    ensure fdmap initialized as identity for single-FD (non-CID) fonts
+
+ src/hb-subset-cff1.cc | 13 ++++++++++---
+ src/hb-subset-cff2.cc |  2 ++
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+commit b403be8ad98ffd2dbe95dad73e96c7ed1295d9fc
+Merge: b67a7c73 50d1a41c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 16 12:29:18 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit b67a7c731f041323c19ab245f0285c304d9ae3d2
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 16 12:28:24 2018 -0800
+
+    drop dotsection as hint along with test case
+
+ src/hb-subset-cff-common.hh             |   4 ++++
+ src/hb-subset-cff1.cc                   |   1 +
+ test/api/fonts/cff1_dotsect.nohints.otf | Bin 0 -> 3132 bytes
+ test/api/fonts/cff1_dotsect.otf         | Bin 0 -> 3220 bytes
+ test/api/test-subset-cff1.c             |  21 +++++++++++++++++++++
+ 5 files changed, 26 insertions(+)
+
+commit 50d1a41c08ad3508a94240b52df03c383ae8f1f8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 08:52:57 2018 -0500
+
+    [coretext] Hopefully the last one
+
+ src/hb-coretext.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0aab861f9cda6fba5ce71562d9f087d924e8a161
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 08:43:25 2018 -0500
+
+    [coretext] Another round
+
+ src/hb-coretext.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 0809b76a9a1d7bd53818df7e83a9c81e664dfe0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 08:29:47 2018 -0500
+
+    [coretext] One more try..
+
+ src/hb-coretext.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 78bd4475946f2d255539306e4b1115f408c54b54
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 04:10:53 2018 -0500
+
+    [coretext] One more try
+
+ src/hb-coretext.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fd27a23c824bbbd4f4c7e75701cc5d287289704b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 03:57:12 2018 -0500
+
+    [coretext] Another build fix attemt
+
+ src/hb-coretext.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 729aedf0da90cbf11235a35588cfdc06ba87a784
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 03:26:46 2018 -0500
+
+    [directwrite] Fix build
+
+ src/hb-directwrite.cc | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit cfb9771a3b096006cbae98438f1ba101d222e0e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 03:24:22 2018 -0500
+
+    [coretext] Try to fix
+
+ src/hb-coretext.cc  | 48 ++++++++++++++++++++++++++++++++++++++----------
+ src/hb-machinery.hh | 15 +++++----------
+ src/hb-shaper.hh    | 44 --------------------------------------------
+ 3 files changed, 43 insertions(+), 64 deletions(-)
+
+commit e3e9547365417e547beec84494c8bf6e4e2947fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 02:55:29 2018 -0500
+
+    [coretext] Unbreak build
+
+ src/hb-coretext.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit ce5da0f36a2ece29c387810a060531df15ad6c7b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 02:29:13 2018 -0500
+
+    [shaper] Rewrite shaper data code to be more template-driven than
+    macro-driven
+
+ src/hb-coretext.cc       |  17 +++----
+ src/hb-directwrite.cc    |   9 +---
+ src/hb-face.cc           |  12 +----
+ src/hb-face.hh           |  13 ++----
+ src/hb-fallback-shape.cc |   5 --
+ src/hb-font.cc           |  14 ++----
+ src/hb-font.hh           |  12 ++---
+ src/hb-graphite2.cc      |  11 ++---
+ src/hb-machinery.hh      |  14 ++----
+ src/hb-ot-shape.cc       |   5 --
+ src/hb-shape-plan.cc     |   4 +-
+ src/hb-shaper-impl.hh    |   9 +---
+ src/hb-shaper.hh         | 117
+ ++++++++++++++++++++++++++++++++---------------
+ src/hb-uniscribe.cc      |  32 +++++--------
+ 14 files changed, 127 insertions(+), 147 deletions(-)
+
+commit cb4bf85b14afb3761a85e3da130f2844ac94a49d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 02:02:24 2018 -0500
+
+    [hdmx] Fix bounds checking
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11351
+
+ src/hb-ot-hdmx-table.hh | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+commit af727b4e629f8b07d7afb809be69d053827f6a51
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 01:55:39 2018 -0500
+
+    [hdmx] Minor
+
+ src/hb-ot-hdmx-table.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 9e9f16c92debecb4caf533fa112898dfec116d98
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 16 01:48:26 2018 -0500
+
+    [subset] Remove invalid glyphs from glypset to retain
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1388
+
+ src/hb-subset-plan.cc | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+commit 072c7aba92d3c92c84454a12578264f12439bb0d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 15 15:41:46 2018 -0800
+
+    use 2-byte offset instead of 4-byte for local subrs
+
+    more than enough since local subrs immediately follow its
+    corresponding private dict, as the result 2-byte redunction for each
+    font dict with local subrs
+    updated api test expected subset fonts accordingly
+
+ src/hb-subset-cff-common.hh                           |   4 ++--
+ test/api/fonts/AdobeVFPrototype.abc.otf               | Bin 7460 ->
+ 7456 bytes
+ test/api/fonts/AdobeVFPrototype.ac.nohints.otf        | Bin 6780 ->
+ 6780 bytes
+ test/api/fonts/AdobeVFPrototype.ac.otf                | Bin 6996 ->
+ 6996 bytes
+ .../fonts/SourceHanSans-Regular.41,4C2E.nohints.otf   | Bin 2380 ->
+ 2376 bytes
+ test/api/fonts/SourceHanSans-Regular.41,4C2E.otf      | Bin 2576 ->
+ 2572 bytes
+ test/api/fonts/SourceSansPro-Regular.abc.otf          | Bin 1812 ->
+ 1808 bytes
+ test/api/fonts/SourceSansPro-Regular.ac.nohints.otf   | Bin 1592 ->
+ 1592 bytes
+ test/api/fonts/SourceSansPro-Regular.ac.otf           | Bin 1708 ->
+ 1704 bytes
+ test/api/fonts/cff1_seac.C0.otf                       | Bin 1604 ->
+ 1600 bytes
+ 10 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 9d0231cfe7c404da3b5bc360ad76180a7aded62c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 15 15:39:43 2018 -0800
+
+    fixed a subset bug when no font dicts reduce
+
+ src/hb-ot-cff-common.hh     | 11 +++++++++++
+ src/hb-subset-cff-common.cc | 24 +++++++++++++-----------
+ src/hb-subset-cff1.cc       | 27 ++++++---------------------
+ src/hb-subset-cff2.cc       | 25 +++++--------------------
+ 4 files changed, 35 insertions(+), 52 deletions(-)
+
+commit 11aa0468ac2c62ff734ba6b0f6eb43d1bd6f602b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 15 23:10:56 2018 +0330
+
+    [subset] minor, adjust spaces
+
+ src/hb-open-type.hh            |  70 ++++++------
+ src/hb-ot-cmap-table.hh        | 182 +++++++++++++++----------------
+ src/hb-ot-glyf-table.hh        | 242
+ ++++++++++++++++++++---------------------
+ src/hb-ot-hdmx-table.hh        |  20 ++--
+ src/hb-ot-hmtx-table.hh        |  14 +--
+ src/hb-ot-layout-common.hh     |  77 ++++++-------
+ src/hb-ot-layout-gpos-table.hh |  16 +--
+ src/hb-ot-layout-gsub-table.hh |   4 +-
+ src/hb-ot-layout-gsubgpos.hh   |  88 +++++++--------
+ src/hb-ot-os2-table.hh         |  24 ++--
+ src/hb-ot-post-table.hh        |  26 ++---
+ src/hb-subset-glyf.cc          | 182 +++++++++++++++----------------
+ src/hb-subset-glyf.hh          |   6 +-
+ src/hb-subset-input.cc         |   4 +-
+ src/hb-subset-plan.cc          |  32 +++---
+ src/hb-subset-plan.hh          |  12 +-
+ src/hb-subset.cc               |  46 ++++----
+ src/hb-subset.h                |   7 +-
+ util/hb-subset.cc              |   2 +-
+ 19 files changed, 510 insertions(+), 544 deletions(-)
+
+commit d7c50ff0d65192fd2b7b80704e227fa108c06de3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 15 23:10:49 2018 +0330
+
+    [math] minor, adjust spaces
+
+ src/hb-ot-math-table.hh | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+commit 13735570f051c4131cdc481939799d76c38c758b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 15 12:10:23 2018 -0800
+
+    reject nested seac
+
+ src/hb-cff1-interp-cs.hh |  4 ++++
+ src/hb-ot-cff1-table.cc  | 11 ++++++-----
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+commit c37aecd41c5b55e5ef496f3c4cc255a1e2ce7f9f
+Merge: ecdb77f0 cabe433f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 15 11:03:46 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit ecdb77f0ae1ef9b129cf9195dbdaa9f6c4425ed5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 15 10:54:15 2018 -0800
+
+    fixed CFF1 subset of std encoding & non-std charset combo
+
+ src/hb-ot-cff-common.hh | 2 --
+ src/hb-ot-cff1-table.hh | 2 ++
+ src/hb-subset-cff1.cc   | 5 +++--
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+commit cabe433fbb81d314ad9e3cbed768dd13983a4477
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 15 02:48:50 2018 -0500
+
+    [base] Add TODO items
+
+ src/hb-ot-layout-base-table.hh | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 3bf1ce748fa89316dd32de28bfdc636495e657fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 14 21:08:54 2018 -0500
+
+    [shaper] Rename
+
+ src/hb-shape-plan.cc |  2 +-
+ src/hb-shape.cc      |  2 +-
+ src/hb-shaper.cc     | 16 ++++++++--------
+ src/hb-shaper.hh     |  4 ++--
+ 4 files changed, 12 insertions(+), 12 deletions(-)
+
+commit c221dc0ba70fd4af94d8f735a9cef1ab92cc6ede
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 14 14:49:34 2018 -0500
+
+    [ot-shape] Move code around
+
+ src/hb-aat-layout-common.hh |  4 ++--
+ src/hb-aat-layout.cc        |  8 ++++----
+ src/hb-aat-layout.hh        |  6 +++---
+ src/hb-ot-layout.cc         |  2 +-
+ src/hb-ot-layout.hh         |  2 +-
+ src/hb-ot-shape.cc          | 44
+ +++++++++++++++++++++++++++++---------------
+ src/hb-ot-shape.hh          |  6 +++---
+ 7 files changed, 43 insertions(+), 29 deletions(-)
+
+commit 892ab37e7c9580e35b35a4d82a99e2ea73ac7b0b
+Merge: 3787c078 7867c2ba
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 14 13:54:07 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit 3787c078561f1157bd04644f092c4467f63c717c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 14 13:38:03 2018 -0800
+
+    Implemented seac for extents & subset along with API tests
+
+ gtk-doc.make                    | 321
+ +++++++++++++++++++++++++++++++++++++++-
+ src/hb-cff-interp-common.hh     |   2 +-
+ src/hb-cff-interp-cs-common.hh  |   7 +
+ src/hb-cff1-interp-cs.hh        |  29 +++-
+ src/hb-ot-cff1-table.cc         | 256 +++++++++++++++++++++++++-------
+ src/hb-ot-cff1-table.hh         |  88 ++++++++---
+ src/hb-subset-plan.cc           |  19 +++
+ test/api/fonts/cff1_seac.C0.otf | Bin 0 -> 1604 bytes
+ test/api/fonts/cff1_seac.otf    | Bin 0 -> 2260 bytes
+ test/api/test-ot-extents-cff.c  |  31 ++++
+ test/api/test-subset-cff1.c     |  19 +++
+ 11 files changed, 699 insertions(+), 73 deletions(-)
+
+commit 7867c2bad05fe48f9e4a1b776fb7da67b747fb4e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Nov 14 22:13:50 2018 +0330
+
+    [STAT] Add table parsing (#1384)
+
+ src/Makefile.sources    |   1 +
+ src/hb-ot-face.hh       |   2 +
+ src/hb-ot-font.cc       |   4 +-
+ src/hb-ot-hmtx-table.hh |  11 +-
+ src/hb-ot-stat-table.hh | 280
+ ++++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 290 insertions(+), 8 deletions(-)
+
+commit 48d16c2ab2b181c733accd4fd9730963e59b6323
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 14 09:56:30 2018 -0500
+
+    [hmtx] Fix signedness issue
+
+    Fixes
+    https://github.com/harfbuzz/harfbuzz/issues/1248#issuecomment-438689499
+
+ src/hb-ot-hmtx-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 29db2a44a6b7a28ade5e288779dbf5a200b43acd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Nov 14 12:13:16 2018 +0330
+
+    [ot-color/svg] Note that it can be gzipped
+
+ src/hb-ot-color.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a9c27d576ffe4452d1a3dae73964a8f4d6dcc088
+Merge: 3c3eb5ea e543e1a0
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Nov 14 08:29:17 2018 +0330
+
+    Merge pull request #1383 from punchcutter/master
+
+    Add test for https://github.com/harfbuzz/harfbuzz/issues/1379
+
+commit e543e1a0858bb5d7384d82600a789d40b62d9821
+Author: punchcutter <zarijoscha@gmail.com>
+Date:   Tue Nov 13 20:44:27 2018 -0800
+
+    Add Grantha test
+
+ .../fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf   | Bin 0 ->
+ 2568 bytes
+ test/shaping/data/in-house/tests/use.tests               |   1 +
+ 2 files changed, 1 insertion(+)
+
+commit 3c3eb5ea9ccf34d33e94f83b9961b3a5e903d196
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 21:10:10 2018 -0500
+
+    [aat] Disable fallback mark advance zeroing and positioning if
+    morx applied
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1357
+
+ src/hb-ot-shape.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit dc4225ccd1d16a1139cbc6092353db9ed03e8980
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 20:48:46 2018 -0500
+
+    Don't retry creating again and again in lazy_loader if create failed
+
+    Still does that if get_null() returns nullptr.  Our shaper data
+    objects
+    are like that.  Shrug.
+
+ src/hb-machinery.hh | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+commit 086235f59310ed77542d4916d31a4285c68630ff
+Merge: 2092f595 c565fc3f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 19:50:25 2018 -0500
+
+    Merge pull request #1382 from punchcutter/master
+
+    Change USE Category for Grantha Virama
+
+commit 2092f595c7a4c591cace41cb99d31620fa6d5fa4
+Merge: 475be9d5 eee5b5ed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 19:49:06 2018 -0500
+
+    Merge pull request #1380 from kbrow1i/cygwin
+
+    Don't use Win32 API on Cygwin
+
+commit c565fc3fb3b14c02e30af28b9d4d4289b0d2e162
+Author: punchcutter <zarijoscha@gmail.com>
+Date:   Tue Nov 13 12:51:10 2018 -0800
+
+    Change USE Category for Grantha Virama
+    https://github.com/harfbuzz/harfbuzz/issues/1379
+
+ src/gen-use-table.py                 | 3 ++-
+ src/hb-ot-shape-complex-use-table.cc | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit 475be9d5c672db6e1764d9425ed7fdaa0dff35c9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 13:01:13 2018 -0500
+
+    Fix Windows build
+
+ src/hb-atomic.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit fc44dea341f1750fec801faed66656b8a58dcded
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 11:54:33 2018 -0500
+
+    Use atomic ints for upem and num_glyphs on face
+
+ src/hb-aat-layout-lcar-table.hh |  3 ++-
+ src/hb-face.cc                  | 10 +++++-----
+ src/hb-face.hh                  | 24 ++++++++++++++----------
+ src/hb-ot-color-sbix-table.hh   |  2 +-
+ src/hb-static.cc                | 13 +++++++++----
+ 5 files changed, 31 insertions(+), 21 deletions(-)
+
+commit 9579ed9755d7c3e47435c55881c9841a5f60ad7e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 11:45:12 2018 -0500
+
+    Make atomic types' internal values non-mutable
+
+    This resulted from confusion previously...
+
+ src/hb-atomic.hh | 10 +++++-----
+ src/hb-object.hh |  2 +-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit c52d5bcd9405dbaa9289d720d9f0853aeac6b244
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 13 11:41:29 2018 -0500
+
+    [ot-face] Add 'head' table
+
+ src/hb-ot-face.hh       |  1 +
+ src/hb-ot-glyf-table.hh | 11 +++--------
+ src/hb-static.cc        |  5 +----
+ 3 files changed, 5 insertions(+), 12 deletions(-)
+
+commit eee5b5ed04f588f618a2251397dd5b850c378627
+Author: Ken Brown <kbrown@cornell.edu>
+Date:   Mon Nov 12 21:05:39 2018 -0500
+
+    Don't use Win32 API on Cygwin
+
+    Cygwin is a Posix platform to the extent possible.  It should use the
+    Posix API except in special circumstances.
+
+ src/hb-atomic.hh                           |  2 +-
+ src/hb-blob.cc                             | 10 +++++-----
+ src/hb-mutex.hh                            |  2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ src/hb.hh                                  |  2 +-
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+commit 56f541d0001f6d7e2e35cdd15217bdf52ebf8391
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 19:46:37 2018 -0500
+
+    [shape-plan] Remove unused code
+
+ src/hb-shape-plan.hh | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+commit 6c22f3fd95617a8c3cd558858c6758a0d548d370
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 19:26:01 2018 -0500
+
+    [shape-plan] Implement fine-grained caching plans with user-features
+
+    Only tag, value, and global-ness of features are considered, not their
+    start/end offsets.
+
+ src/hb-shape-plan.cc | 69
+ ++++++++++++++++++++++++++++++----------------------
+ src/hb-shape-plan.hh | 17 ++-----------
+ 2 files changed, 42 insertions(+), 44 deletions(-)
+
+commit cc8428756a1b18b0445c2c5fbb38e05453693dad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 18:48:10 2018 -0500
+
+    [shape-plan] Cache shape plans with variations based on variation
+    indices
+
+ src/hb-aat-map.cc    |  4 +---
+ src/hb-aat-map.hh    |  4 +---
+ src/hb-ot-map.cc     | 18 +++++------------
+ src/hb-ot-map.hh     |  6 +++---
+ src/hb-ot-shape.cc   | 13 +++++--------
+ src/hb-ot-shape.hh   | 28 +++++++++++++++++++++++---
+ src/hb-shape-plan.cc | 55
+ ++++------------------------------------------------
+ src/hb-shape-plan.hh | 23 ++++++++++++++++++----
+ 8 files changed, 63 insertions(+), 88 deletions(-)
+
+commit 8284cb9fb3600268e06d8a2ba8400700510de7a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 18:18:20 2018 -0500
+
+    [shape-plan] Refactor more
+
+ src/hb-shape-plan.cc | 46 ++++++++++++++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 20 deletions(-)
+
+commit 1082338525c96206f43785e283e41b3e959871fd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 18:05:02 2018 -0500
+
+    [shape-plan] Only use shape-plan key to initialize hb_ot_shape_plan_t
+
+    Such that we don't accidentally use info not in the cache key.
+
+ src/hb-ot-shape.cc   | 25 +++++++++++--------------
+ src/hb-ot-shape.hh   |  8 +++-----
+ src/hb-shape-plan.cc |  7 +------
+ 3 files changed, 15 insertions(+), 25 deletions(-)
+
+commit 7ac03f88a22325fb4d6b77ee7694ad11f6a99bcb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 17:50:30 2018 -0500
+
+    [shape-plan] Minor
+
+ src/hb-shape-plan.cc | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+commit c7be933439af1bc8251b2b19df75b42bd0f3bdb5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 17:49:15 2018 -0500
+
+    [shape-plan] Refactor some more
+
+ src/hb-shape-plan.cc | 147
+ ++++++++++++++++++++++++++++-----------------------
+ src/hb-shape-plan.hh |  15 ++++++
+ 2 files changed, 95 insertions(+), 67 deletions(-)
+
+commit fc27777833e052dab91ca5777802e6c4e956deb4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 17:27:34 2018 -0500
+
+    [shape-plan] Refactor more
+
+ src/hb-shape-plan.cc | 44 +++++++++++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 21 deletions(-)
+
+commit 566612295b7c9bc003e9f1723f2491113724b788
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 17:19:45 2018 -0500
+
+    [shape-plan] Turn hb_shape_plan_proposal_t into hb_shape_plan_key_t
+
+    And include it in hb_shape_plan_t itself.
+
+ src/hb-shape-plan.cc | 206
+ +++++++++++++++++++--------------------------------
+ src/hb-shape-plan.hh |  27 +++----
+ 2 files changed, 92 insertions(+), 141 deletions(-)
+
+commit af123bd1b814b4fb881ea3d11f1ef0bcced75942
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 16:27:08 2018 -0500
+
+    Add hb_memcmp()
+
+ src/hb-dsalgs.hh | 17 ++++++++++++-----
+ src/hb-set.hh    |  2 +-
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+commit 65456bff37ef61094c35574a35c96f6437fd6015
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 16:15:26 2018 -0500
+
+    [shape-plan] Minor
+
+ src/hb-shape-plan.cc | 15 ++++++++-------
+ src/hb-shape-plan.hh |  9 +++++----
+ 2 files changed, 13 insertions(+), 11 deletions(-)
+
+commit 1db672a5e903de39f955e70b8814c275ccbe1b5c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 16:05:09 2018 -0500
+
+    [shaper] Rename
+
+ src/hb-shape-plan.cc |  2 +-
+ src/hb-shape.cc      |  2 +-
+ src/hb-shaper.cc     | 16 ++++++++--------
+ src/hb-shaper.hh     |  4 ++--
+ 4 files changed, 12 insertions(+), 12 deletions(-)
+
+commit 5212cd8af2171b9d0e9b78196e7758c37f148b80
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 14:25:18 2018 -0500
+
+    [fuzzing] Add new test
+
+ ...zz-testcase-minimized-hb-shape-fuzzer-5754863779053568 | Bin 0 ->
+ 100 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 274f4c726f461f49f54a79557d63bf95d22903cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 14:24:36 2018 -0500
+
+    Rename check_array2() to check_array()
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-machinery.hh             | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit e014405a214bceff3a1ce80f0b98273c44078e82
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 14:23:31 2018 -0500
+
+    Rename check_array(array, a, b) to check_range()
+
+ src/hb-aat-layout-common.hh    |  8 ++++++--
+ src/hb-machinery.hh            | 31 +++++++++++++++++++++++--------
+ src/hb-open-type.hh            |  4 +++-
+ src/hb-ot-layout-common.hh     |  5 +++--
+ src/hb-ot-layout-gpos-table.hh | 11 ++++++++---
+ src/hb-ot-var-hvar-table.hh    |  4 +++-
+ src/hb-ot-var-mvar-table.hh    |  4 +++-
+ 7 files changed, 49 insertions(+), 18 deletions(-)
+
+commit c8f4cc49272d8bcd47706a6306a625d724349f5a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 14:11:29 2018 -0500
+
+    [kerx] Fix integer overflow in multiply
+
+    Fixes https://oss-fuzz.com/v2/testcase-detail/5754863779053568
+
+ src/hb-aat-layout-kerx-table.hh |  2 +-
+ src/hb-machinery.hh             | 29 ++++++++++++++++-------------
+ 2 files changed, 17 insertions(+), 14 deletions(-)
+
+commit 1300f027a938d8898cdc9abbcad71afadf70e6e6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 13:56:48 2018 -0500
+
+    [kerx] Minor tweak on previous commit
+
+ src/hb-aat-layout-kerx-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit d6666b3866037c9d3e8a497958af9ba8d2f47a73
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 13:21:14 2018 -0500
+
+    [fuzzing] Remove limited-edition build of libraries
+
+    Use normal, production, shared libraries.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1237
+
+ src/Makefile.am          | 31 -------------------------------
+ test/fuzzing/Makefile.am | 39 +++++++++++++--------------------------
+ 2 files changed, 13 insertions(+), 57 deletions(-)
+
+commit a549aa14a0b60436a16f7f8924a5b5f82b4d5b7e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 12 13:01:22 2018 -0500
+
+    [kerx] Protect against stack underflow
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11367
+
+ src/hb-aat-layout-kerx-table.hh                            |   2 +-
+ ...uzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 | Bin 0 ->
+ 69 bytes
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 41a8bc7fd9399def8f580b02627a77f3972cc0e9
+Merge: 0dfa584c 77bd0a64
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Nov 12 08:49:00 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit 0dfa584cb4af6be2852d038e9bd591f67ea9fc6e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Nov 12 08:47:07 2018 -0800
+
+    changed Adobe company name
+
+ src/hb-cff-interp-common.hh      | 2 +-
+ src/hb-cff-interp-cs-common.hh   | 2 +-
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ src/hb-cff1-interp-cs.hh         | 2 +-
+ src/hb-cff2-interp-cs.hh         | 2 +-
+ src/hb-ot-cff-common.hh          | 2 +-
+ src/hb-ot-cff1-table.cc          | 2 +-
+ src/hb-ot-cff1-table.hh          | 2 +-
+ src/hb-ot-cff2-table.cc          | 2 +-
+ src/hb-ot-cff2-table.hh          | 2 +-
+ src/hb-ot-vorg-table.hh          | 2 +-
+ src/hb-subset-cff-common.cc      | 2 +-
+ src/hb-subset-cff-common.hh      | 2 +-
+ src/hb-subset-cff1.cc            | 2 +-
+ src/hb-subset-cff1.hh            | 2 +-
+ src/hb-subset-cff2.cc            | 2 +-
+ src/hb-subset-cff2.hh            | 2 +-
+ test/api/test-ot-extents-cff.c   | 2 +-
+ test/api/test-subset-cff1.c      | 2 +-
+ test/api/test-subset-cff2.c      | 2 +-
+ 20 files changed, 20 insertions(+), 20 deletions(-)
+
+commit 3e284e02c2a5da758526360a45364a330b8ab8e9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 22:51:34 2018 -0500
+
+    [shape-plan] Minor
+
+ src/hb-ot-shape.cc   | 26 ++++++++++++++------------
+ src/hb-ot-shape.hh   | 15 ++++++++-------
+ src/hb-shape-plan.cc |  3 ++-
+ 3 files changed, 24 insertions(+), 20 deletions(-)
+
+commit 420c9de6447cdb491184e7f8caf0811b0c962c05
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 22:38:05 2018 -0500
+
+    [shape-plan] Minor rename
+
+ src/hb-shape-plan.cc | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+commit 77bd0a6458a9169df59f6be667a8eb79bd353dc9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 22:08:48 2018 -0500
+
+    Add variation coords to shape_plan proposal
+
+    This is the root cause of bug worked around in
+    19e77e01bc13f44138e1d50533327d314dd0a018.
+
+    Still no shape plan caching for variations though.
+
+ src/hb-shape-plan.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 9c767d075d0be85227b8dc146061de9bd24f3fec
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 22:03:15 2018 -0500
+
+    Minor
+
+ src/hb-shape-plan.cc | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+commit f521a28b4aad1566664cf14d70a911728ee0b962
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 21:32:01 2018 -0500
+
+    Embed hb_ot_shape_plan_t into hb_shape_plan_t
+
+    No other shaper will need shape_plan_data, by definition.  So, remove
+    abstraction layer and always create hb_ot_shape_plan_t as part of
+    hb_shape_plan_t.
+
+ src/hb-coretext.cc       | 45 ----------------------
+ src/hb-directwrite.cc    | 21 ----------
+ src/hb-fallback-shape.cc | 22 -----------
+ src/hb-graphite2.cc      | 22 -----------
+ src/hb-ot-shape.cc       | 99
+ ++++++++++++++++++++++--------------------------
+ src/hb-ot-shape.hh       | 21 +++++-----
+ src/hb-shape-plan.cc     | 22 ++++++-----
+ src/hb-shape-plan.hh     |  3 +-
+ src/hb-uniscribe.cc      | 22 -----------
+ 9 files changed, 70 insertions(+), 207 deletions(-)
+
+commit fabb01210433ce1c6d5f630bc270f82a8a4a4014
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 17:10:23 2018 -0500
+
+    Remove wrong comment
+
+ src/hb-shape-plan.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 1fd183ee1c40e2eedf86b5e82d1b547c5650ebf5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 16:47:52 2018 -0500
+
+    Finish off eecccc919ce15f60ae7ef9da5cfb311b4aa05c63
+
+ src/hb-machinery.hh | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+commit 1beacdded9cd1e4467b52244cdfd8497516eb107
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 16:35:28 2018 -0500
+
+    Minor
+
+ src/hb-coretext.cc       | 8 ++++----
+ src/hb-directwrite.cc    | 4 ++--
+ src/hb-fallback-shape.cc | 4 ++--
+ src/hb-graphite2.cc      | 4 ++--
+ src/hb-ot-shape.cc       | 4 ++--
+ src/hb-shaper.hh         | 3 ++-
+ src/hb-uniscribe.cc      | 4 ++--
+ 7 files changed, 16 insertions(+), 15 deletions(-)
+
+commit e88d47b7f2f9aee5b0b3cdc0b8f708884175a71f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 16:25:43 2018 -0500
+
+    Minor
+
+ src/hb-face.cc | 2 +-
+ src/hb-face.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 55c66c7c56c1ecd493f51fe66fd434b28addfb41
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 16:09:38 2018 -0500
+
+    Revert "Declare Null() constexpr"
+
+    This reverts commit 442a72d95ab1fb3a47b486d8d1eb68e909d0ffb8.
+
+    Doesn't make sense.  No idea how my local compilers where happy
+    with it!
+
+ src/hb-null.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 98c6f03ccdd0630282ea0b166f66dcfb2a9c1f51
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 15:54:20 2018 -0500
+
+    Minor
+
+ src/hb-face.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 442a72d95ab1fb3a47b486d8d1eb68e909d0ffb8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 15:51:23 2018 -0500
+
+    Declare Null() constexpr
+
+ src/hb-null.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit eecccc919ce15f60ae7ef9da5cfb311b4aa05c63
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 15:48:47 2018 -0500
+
+    Don't store to null object
+
+    Ouch :).
+
+ src/hb-machinery.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 903856ab505cbc6b756d7b904650df72e90f67a7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 15:45:58 2018 -0500
+
+    Remove unused function
+
+ src/hb-machinery.hh | 5 -----
+ 1 file changed, 5 deletions(-)
+
+commit 0e0af11c62c6a55248a5d3c8868da91ef36384c5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 12:54:16 2018 -0500
+
+    [hdmx] Renames
+
+ src/hb-ot-hdmx-table.hh | 46
+ +++++++++++++++++++++++-----------------------
+ 1 file changed, 23 insertions(+), 23 deletions(-)
+
+commit da6aa3b0333de3f2169a5cfcb33374e1b2fe346e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 11:40:57 2018 -0500
+
+    Add hb_blob_ptr_t.destroy()
+
+ src/hb-blob.hh                 | 1 +
+ src/hb-ot-cmap-table.hh        | 2 +-
+ src/hb-ot-color-cbdt-table.hh  | 4 ++--
+ src/hb-ot-color-sbix-table.hh  | 2 +-
+ src/hb-ot-color-svg-table.hh   | 2 +-
+ src/hb-ot-glyf-table.hh        | 4 ++--
+ src/hb-ot-hmtx-table.hh        | 6 +++---
+ src/hb-ot-layout-gdef-table.hh | 2 +-
+ src/hb-ot-layout-gsubgpos.hh   | 2 +-
+ src/hb-ot-name-table.hh        | 2 +-
+ src/hb-ot-post-table.hh        | 2 +-
+ 11 files changed, 15 insertions(+), 14 deletions(-)
+
+commit bb9abb4efd7d72198ffe8abb137ccf07ae17743e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:39:52 2018 -0500
+
+    [hmtx/port] Use hb_blob_ptr_t
+
+ src/hb-ot-hmtx-table.hh | 24 ++++++++++--------------
+ src/hb-ot-post-table.hh | 11 +++++------
+ 2 files changed, 15 insertions(+), 20 deletions(-)
+
+commit 0e2680a6e8d16afd38ffdb6e8cf244150a5e3837
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:28:47 2018 -0500
+
+    [cmap] Port to hb_blob_ptr_t
+
+    Although didn't need it...
+
+ src/hb-ot-cmap-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 0b0fad3ea8888d57d1e077077f5897d1901c5371
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:26:55 2018 -0500
+
+    [color] Port to hb_blob_ptr_t
+
+    Fix hb_blob_ptr_t::get_length () as well.
+
+ src/hb-blob.hh                |  2 +-
+ src/hb-ot-color-cbdt-table.hh | 38 +++++++++++++-------------------------
+ src/hb-ot-color-sbix-table.hh | 10 ++++------
+ src/hb-ot-color-svg-table.hh  | 11 +++++------
+ src/hb-ot-glyf-table.hh       | 22 ++++++++--------------
+ 5 files changed, 31 insertions(+), 52 deletions(-)
+
+commit 925b7a214f06b83b6f2278052656dabc4ebdd6b7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:17:30 2018 -0500
+
+    Comment
+
+ src/hb-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit dcb63868333ba8e229fd8756377151440dd9fd23
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:16:17 2018 -0500
+
+    [shape-plan] Remove use of custom null object
+
+ src/hb-shape-plan.cc | 24 ------------------------
+ src/hb-shape-plan.hh |  1 -
+ 2 files changed, 25 deletions(-)
+
+commit 109891d49876de4de14a91adefbdf681c2b9acc2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:15:08 2018 -0500
+
+    [shape-plan] Make null object all zeros
+
+    To remove custom null object next..
+
+ src/hb-shape-plan.cc | 8 ++++----
+ src/hb-shape-plan.hh | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 34185ff3bc7ece5620145fc05da07c79da950f34
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:12:30 2018 -0500
+
+    [blob] Use default null object
+
+ src/hb-blob.cc | 12 ------------
+ src/hb-blob.hh |  1 -
+ 2 files changed, 13 deletions(-)
+
+commit 2ee1d9f555fba60342bab63294a6dacca10466de
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 11 00:11:28 2018 -0500
+
+    [blob] Change null object memory mode to DUPLICATE
+
+    We never rely on that being equal to readonly.  Just not being
+    writable.  Maybe not even that given that the object is inert.
+
+    In prep for next commit, using default null pool.
+
+ src/hb-blob.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5d0078a48b246e713817e5bb6b4efada9618bea3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 23:52:15 2018 -0500
+
+    Add hb_blob_ptr_t
+
+    Use in a couple of places.  Push to bots to see how many unhappy
+    before
+    I convert the rest.
+
+ src/hb-blob.hh                 | 23 +++++++++++++++++++++++
+ src/hb-ot-layout-gdef-table.hh |  5 ++---
+ src/hb-ot-layout-gsubgpos.hh   |  8 +++-----
+ src/hb-ot-layout.cc            | 14 ++++++--------
+ src/hb-ot-name-table.hh        | 12 +++++-------
+ 5 files changed, 39 insertions(+), 23 deletions(-)
+
+commit e44046ec499949884b9b77c4c9937ad381386850
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 22:41:35 2018 -0500
+
+    Minor
+
+ src/hb-ot-layout.cc | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 752bd8a192af209f44dacaf1d3510d0bfc6354b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 21:13:13 2018 -0500
+
+    [kerx] Fix Format1 tupleKern sanitization
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11312
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11305
+
+ src/hb-aat-layout-kerx-table.hh                            |   6 +++---
+ ...uzz-testcase-minimized-hb-shape-fuzzer-5629524117553152 | Bin 0 ->
+ 93 bytes
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit f9e0552debc45afedd86c848484bcd169af62dc2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 21:01:49 2018 -0500
+
+    [fuzzing] Make "make lib" faster and more usable
+
+ src/Makefile.am          |  2 +-
+ test/fuzzing/Makefile.am | 12 +++++++-----
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+commit 4674655841bb810e7b68f03431d7b5a7c34c6f20
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 20:11:10 2018 -0500
+
+    Minor
+
+ src/hb-ot-shape-complex-arabic-fallback.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit a953b647507fe2ae8f5187fbfb04e69d2a2952e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 20:10:03 2018 -0500
+
+    Revert parts of previous commit that made clang unhappy
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1d66cdcf770e45d995a318592352e4349faecb71
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 19:54:08 2018 -0500
+
+    Better fix for MSVC 2008
+
+    Follow up on b4c61130324455bfd42095b01fa14ac901e441f1
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1374
+
+ src/hb-machinery.hh            | 8 ++++----
+ src/hb-open-type.hh            | 8 ++++++++
+ src/hb-ot-cmap-table.hh        | 4 ++--
+ src/hb-ot-layout-gpos-table.hh | 4 ++--
+ src/hb-ot-var-avar-table.hh    | 9 ++++-----
+ 5 files changed, 20 insertions(+), 13 deletions(-)
+
+commit fb2a037f54f3cd323a447925f6534eccd1c709c1
+Merge: 87984165 b4c61130
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Nov 10 16:23:11 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit b4c61130324455bfd42095b01fa14ac901e441f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 16:35:39 2018 -0500
+
+    Try fixing MSVC 2008 build
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1374
+
+ src/hb-open-type.hh | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+commit f2e942f3023e3c5cb3e732ee7b4782b3df170a85
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 16:11:14 2018 -0500
+
+    Fix hb_bytes_t's unused template array constructor
+
+ src/hb-dsalgs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6213a75b68825037fbaf6f5ad4eef66e8bad4b3c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 16:09:21 2018 -0500
+
+    Add trivial casts to hb_bytes_t
+
+ src/hb-dsalgs.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 8bb97d2ce140b7fe81d0726c32e024d887e0be1c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 15:54:33 2018 -0500
+
+    Revert back hb_bytes_t.cmp() to the scheme it was
+
+    But fix UBSan complaint.
+
+    There's nothing in hb_bytes_t that guarantees lexical ordering, and
+    ordering by length first is much faster.
+
+ src/hb-dsalgs.hh | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+commit 534e1d7694c96f61e853daef481b41274d5d16d8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 15:43:16 2018 -0500
+
+    Fix hb_bytes_t.cmp() for realz this time
+
+ src/hb-dsalgs.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 929f07dbfc8b8c40771d27a502f6e5842c1c1e90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 15:38:48 2018 -0500
+
+    Fix hb_bytes_t.cmp()
+
+    Ouch!
+
+ src/hb-dsalgs.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 5547bfa9f2815df727fa524b0ea0f136a6f955b7
+Merge: 3a9fa8c0 1d82b476
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 15:35:12 2018 -0500
+
+    Merge pull request #1376 from ebraminio/minor
+
+    [colr/feat/trak] minor
+
+commit 1d82b4761d0a2e2e0be002e8a6bfe060f7b6dec3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 10 18:08:11 2018 +0330
+
+    [colr/feat/trak] minor
+
+ src/hb-aat-layout-feat-table.hh | 14 +++++++-------
+ src/hb-aat-layout-trak-table.hh | 35 +++++++++++++++++++----------------
+ src/hb-ot-color-colr-table.hh   | 18 ++++++------------
+ 3 files changed, 32 insertions(+), 35 deletions(-)
+
+commit 3a9fa8c026bf28bf87e20ec95327f74fd7070b74
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 01:56:37 2018 -0500
+
+    [qsort] Fix O(N^2) behavior if all array elements are the same
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11327
+
+    Reported as https://github.com/noporpoise/sort_r/issues/7
+
+ src/hb-dsalgs.hh                                        |  15
+ +++++++++++----
+ ...-testcase-minimized-hb-shape-fuzzer-5634443633491968 | Bin 0 ->
+ 41814 bytes
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+
+commit b308aaccf0773e252880b9b887f3d3d1dec00168
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 00:37:17 2018 -0500
+
+    [post] Minor
+
+ src/hb-ot-post-table.hh | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+commit 4111c3b8cd1b1c44f722877614ec1ee25111e78c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 00:26:36 2018 -0500
+
+    [post] Move sanitize close to data fields
+
+ src/hb-ot-post-table.hh | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit e26e6dbb336e48a5898738dbbd9e56e3a00b7bed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 10 00:19:50 2018 -0500
+
+    [post] Remove unnecessary hb_nonnull_ptr_t<>
+
+ src/hb-ot-post-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6b8178c6499f8d0ee45a57332af778af0e48d1b5
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 10 02:42:08 2018 +0330
+
+    [glyf] minor
+
+ src/hb-ot-glyf-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 87984165877c90bf4e0a0418a6407e44c048335d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 9 08:59:18 2018 -0800
+
+    fixed vstem handling (lack thereof) in check_width
+
+    bug exposed by U+2261 equivalence in SourceCodePro-Regular.otf
+
+ src/hb-cff1-interp-cs.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 5f97fe9956274d9de4e7813d7f2e850d9ffd8224
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 9 10:01:50 2018 -0500
+
+    Fix a few MSVC 2008 warnings
+
+    https://github.com/harfbuzz/harfbuzz/issues/1374
+
+ src/hb-set.hh    | 4 ++--
+ src/hb-vector.hh | 3 +++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+commit f51bb6ee7bd4ebca9b432851adc527ec086360fe
+Merge: 2d987110 b986fead
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 8 14:42:40 2018 -0500
+
+    Merge pull request #1358 from ebraminio/lcar
+
+    Hook AAT's lcar to _get_ligature_carets
+
+commit b986fead0aee52d219ce85dd49c9109bfaf31801
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Nov 5 12:31:58 2018 +0330
+
+    Hook AAT's lcar to _get_ligature_carets
+
+ src/Makefile.sources               |   1 +
+ src/hb-aat-layout-lcar-table.hh    |  92
+ +++++++++++++++++++++++++++++++++++++
+ src/hb-ot-face.hh                  |   1 +
+ src/hb-ot-layout-gdef-table.hh     |   6 +--
+ src/hb-ot-layout.cc                |  17 ++++---
+ test/api/Makefile.am               |   1 +
+ test/api/fonts/lcar.ttf            | Bin 0 -> 808 bytes
+ test/api/test-ot-ligature-carets.c |  67 +++++++++++++++++++++++++++
+ 8 files changed, 175 insertions(+), 10 deletions(-)
+
+commit 2d987110c067ccbf63b1399d2a87820121925e39
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 8 21:46:26 2018 +0330
+
+    [aat] Minor
+
+ src/hb-aat-layout-just-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9fae611740f514e5fc101a18c4551a20b4a47b59
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 8 12:17:09 2018 -0500
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/DISABLED          |  1 +
+ test/shaping/data/text-rendering-tests/Makefile.sources  |  2 +-
+ .../data/text-rendering-tests/tests/MORX-31.tests        | 16
+ ++++++++--------
+ 3 files changed, 10 insertions(+), 9 deletions(-)
+
+commit b989507fa6b36eb9950001d4e28f3946ffbe75f9
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 8 20:48:54 2018 +0330
+
+    [aat] Minor (#1369)
+
+ src/hb-aat-layout-just-table.hh | 11 ++++++-----
+ src/hb-aat-layout-trak-table.hh | 12 ++++++------
+ 2 files changed, 12 insertions(+), 11 deletions(-)
+
+commit 26c291aaa023d31c793b6f505c76e0dd7acbff9b
+Merge: 417963dd f9042384
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 8 09:06:49 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit 417963dd9f93a316e672c77493e763978bfdbc28
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 8 09:01:20 2018 -0800
+
+    got rid of Remap::fullset() as incorrect, redundant, inefficient
+
+ src/hb-ot-cff-common.hh | 22 ----------------------
+ 1 file changed, 22 deletions(-)
+
+commit f90423847b07ff9c9f66be6dfa3b6071f9c7d9d3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 8 19:17:02 2018 +0330
+
+    [just] Initial table implementation (#1364)
+
+    A starting point, its sanitization is not tested however
+
+ src/Makefile.sources            |   1 +
+ src/hb-aat-layout-just-table.hh | 416
+ ++++++++++++++++++++++++++++++++++++++++
+ src/hb-aat-layout.cc            |   1 +
+ 3 files changed, 418 insertions(+)
+
+commit b8b00fb3c60d23efca5720db15555c4a01c56a45
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 8 18:53:14 2018 +0330
+
+    [aat] Support Lookup<OffsetTo<>>, needed by just and lcar (#1368)
+
+ src/hb-aat-layout-common.hh | 57
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-open-type.hh         | 11 +++++++++
+ 2 files changed, 68 insertions(+)
+
+commit 073d0a9fbcf4f9cf44878f3f91afa27615b14e5c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 8 10:59:50 2018 +0330
+
+    [ci] minor
+
+ .circleci/config.yml | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 15326826bf20f1f3d5ef3ddde2ad17b0ccbfa605
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 21:58:04 2018 -0500
+
+    [aat] Ignore cross-stream offset of deleted-glyphs
+
+    I think it makes sense to accumulate it, but Ned tells me that's
+    what CoreText does.
+
+ src/hb-aat-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 636a6833c57eb88ebaa92034c1f4722471f70781
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 17:58:45 2018 -0800
+
+    fixed ends_in_hint bug
+
+    subr ends in hint itself should be regarded as hint
+    this flag should propagate to its caller if the call itself is at
+    the end of the caller
+
+ src/hb-subset-cff-common.hh | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+commit 0bf76154f1bb15aa2fc361eb725977313f103a58
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 19:11:43 2018 -0500
+
+    [fuzzing] Take whatever text we can
+
+ test/fuzzing/hb-shape-fuzzer.cc | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+commit 517a1bac97b6273e03562deefcca129648698c31
+Merge: 9d502769 b18a56a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 18:40:48 2018 -0500
+
+    Merge pull request #1362 from harfbuzz/cross-kern
+
+    Vastly improve kern/kerx tables, including cross-stream "kerning"
+
+commit b18a56a290bf5330e81019b33f15e6951dd86a8b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 18:13:22 2018 -0500
+
+    [kerx] Comment
+
+ src/hb-aat-layout-kerx-table.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 4d740206943ecb72e4be7cc4815e0a3aa3edaa9d
+Merge: e0c30b96 9d502769
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 15:09:30 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit e0c30b961de87d38bff8dd49e86785a5b74fcad3
+Merge: 0996c0ff ae8fd0db
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 15:08:55 2018 -0800
+
+    merge with cff-subset branch
+
+commit 006386be3a069199ebaf22bcc55fa7233c62e0d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 18:04:53 2018 -0500
+
+    [kern] Implement negative state numbers
+
+    Let the fuzzing bots rip this code apart...
+
+ src/hb-aat-layout-common.hh     | 90
+ ++++++++++++++++++++++++++++++-----------
+ src/hb-aat-layout-kerx-table.hh | 10 -----
+ 2 files changed, 66 insertions(+), 34 deletions(-)
+
+commit 0996c0ff6279f377e2b14f08663df2ce82de2b14
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 14:48:37 2018 -0800
+
+    implented no-desubroutinize with CFF2 along with API test
+
+    replaced AdobeVFPrototype.abc.otf with a hinted (maually) &
+    subroutinized copy
+    replaced expected results as well
+
+ src/hb-cff-interp-dict-common.hh                   |   4 +-
+ src/hb-cff2-interp-cs.hh                           |  16 +-
+ src/hb-ot-cff-common.hh                            |  22 +--
+ src/hb-subset-cff-common.hh                        |  64 +++++---
+ src/hb-subset-cff2.cc                              | 180
+ ++++++++++++++++++---
+ test/api/fonts/AdobeVFPrototype.abc.nohints.otf    | Bin 7800 -> 0 bytes
+ test/api/fonts/AdobeVFPrototype.abc.otf            | Bin 7800 ->
+ 7460 bytes
+ test/api/fonts/AdobeVFPrototype.ac.nohints.otf     | Bin 7152 ->
+ 6780 bytes
+ .../fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf  | Bin 0 -> 6844 bytes
+ test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf     | Bin 0 -> 7060 bytes
+ test/api/fonts/AdobeVFPrototype.ac.otf             | Bin 7336 ->
+ 6996 bytes
+ test/api/test-subset-cff2.c                        |  51 +++++-
+ 12 files changed, 271 insertions(+), 66 deletions(-)
+
+commit 29c5302376ff2bc8f04b0fc0efba3ce40ef564a7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 17:29:37 2018 -0500
+
+    [morx] Minor
+
+ src/hb-aat-layout-morx-table.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 385f78b3123f268e4c7ff423621e5ce9e8a5c54b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 17:19:21 2018 -0500
+
+    [aat] Remove deleted-glyhs after applying kerx/kern
+
+    Finally:  Fixes https://github.com/harfbuzz/harfbuzz/issues/1356
+
+    Test case:
+    $ ./hb-shape GeezaPro.ttc -u U+0628,U+064A,U+064E,U+0651,U+0629
+    [u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
+
+    The mark positioning (kern table CrossStream kerning) only works
+    if deleted
+    glyph (as result of ligation) is still in stream and pushed through
+    the
+    state machine.
+
+ src/hb-aat-layout-morx-table.hh |  16 -------
+ src/hb-aat-layout.cc            |  30 ++++++++++--
+ src/hb-aat-layout.hh            |  12 +++--
+ src/hb-ot-layout-gpos-table.hh  |   6 +--
+ src/hb-ot-layout.cc             |  60 +++++++++++++++++++++--
+ src/hb-ot-layout.hh             |  23 +++++----
+ src/hb-ot-shape.cc              | 102
+ ++++++++++++++--------------------------
+ 7 files changed, 142 insertions(+), 107 deletions(-)
+
+commit 1909072235e59eb80f9169300279b65779b932a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:42:16 2018 -0500
+
+    [aat] Add debug info to state machine
+
+ src/hb-aat-layout-common.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit ca23567f41a2d6389f6fd2483a994cf5aa6aeaf8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:19:51 2018 -0500
+
+    Disable fallback mark positioning if kern table has cross-stream
+    kerning
+
+    Happens even if the cross-stream kerning is for cursive attachment
+    only.  Oh well..
+
+ src/hb-ot-layout.cc |  6 ++++++
+ src/hb-ot-layout.hh |  3 +++
+ src/hb-ot-shape.cc  | 14 ++++++--------
+ src/hb-ot-shape.hh  |  2 +-
+ 4 files changed, 16 insertions(+), 9 deletions(-)
+
+commit 5cf6f94dfd30a468ab8464435e846811c39d9226
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:07:22 2018 -0500
+
+    Don't apply both kerx and kern
+
+    Ouch!
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 41cff7afc916048810a7ea4aa33ecdee7401df74
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:05:36 2018 -0500
+
+    Minor
+
+ src/hb-ot-shape.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 9af983af24788afad4b37bd2297b86cdca7c5c29
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:03:09 2018 -0500
+
+    [kern] Switch to dispatch
+
+ src/hb-aat-layout-kerx-table.hh |  7 +++++--
+ src/hb-ot-kern-table.hh         | 28 +++++++++++++++-------------
+ src/hb-ot-layout.cc             |  6 ++----
+ 3 files changed, 22 insertions(+), 19 deletions(-)
+
+commit bc06e2805ae55f5c152dfb70ee91c75830ad8f54
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 16:02:40 2018 -0500
+
+    [kerx/kern] Add has_cross_stream()
+
+ src/hb-aat-layout-kerx-table.hh | 15 +++++++++++++++
+ src/hb-ot-kern-table.hh         |  9 +++++++++
+ 2 files changed, 24 insertions(+)
+
+commit ea579f9ccc87718d4c2ca8945a997e6679428a12
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 15:44:40 2018 -0500
+
+    [kerx] Fix peculiar indexing that was needed previously
+
+    Not needed now that we use GPOS attachment for cursive kerx.
+
+ src/hb-aat-layout-kerx-table.hh | 20 +++++++-------------
+ 1 file changed, 7 insertions(+), 13 deletions(-)
+
+commit 6ee6cd93d8c61389cf242e42a531cc6e7214b21a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 15:40:55 2018 -0500
+
+    [GPOS] Only mark unsafe-to-break if kerning happened
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1365
+
+ src/hb-ot-layout-gpos-table.hh | 56
+ ++++++++++++++++++++++++------------------
+ 1 file changed, 32 insertions(+), 24 deletions(-)
+
+commit 501a364d9bb6c5828f9d660bae8b6e93b158b275
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 15:02:16 2018 -0500
+
+    [GPOS] Add TODO item
+
+ src/hb-ot-layout-gpos-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 7a9629f2f11a11d1c064662a08a0172ac2001668
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 14:52:36 2018 -0500
+
+    [kerx] Implement CrossStream kerning for non-state-machine subtables
+
+    Untested.
+
+ src/hb-aat-layout-kerx-table.hh | 12 ++++++------
+ src/hb-kern.hh                  | 43
+ +++++++++++++++++++++++++++++------------
+ src/hb-ot-kern-table.hh         |  4 ++--
+ 3 files changed, 39 insertions(+), 20 deletions(-)
+
+commit 0eb4157011e78c332d781e28b54b020aa08957c0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 14:42:15 2018 -0500
+
+    [kerx] Disable backwards-kerning for non-state-machine tables
+
+    That's what the spec says for Backwards flag, only applicable to
+    formats 1 and 4.
+
+ src/hb-aat-layout-kerx-table.hh | 8 +++-----
+ src/hb-ot-kern-table.hh         | 2 +-
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+commit b2f687c2569a3cc0b1cd0335c5ca0f8d193f8a39
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 14:38:29 2018 -0500
+
+    [kerx] Use GPOS attachment facilities for CrossStream kerning
+
+ src/hb-aat-layout-kerx-table.hh | 51
+ ++++++++++++++++++++++++++++-------------
+ 1 file changed, 35 insertions(+), 16 deletions(-)
+
+commit e10a856eb24ae45e301c3ffa778caa4c0a995bb9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 14:11:48 2018 -0500
+
+    [kerx] Format
+
+ src/hb-aat-layout-kerx-table.hh | 58
+ ++++++++++++++++++++---------------------
+ 1 file changed, 28 insertions(+), 30 deletions(-)
+
+commit 649cc3ef2773950b0b5884d9d1caf414aac888bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 14:04:04 2018 -0500
+
+    [kerx] Don't disable crossKerning if kern feature is off
+
+ src/hb-aat-layout-kerx-table.hh | 9 +++++----
+ src/hb-ot-shape.cc              | 2 +-
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+commit 0c3b061ac244fa8a8657366e1b95523503fdf7be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:58:41 2018 -0500
+
+    [kern] Apply erlier, where GPOS/kerx are applied
+
+ src/hb-aat-layout-kerx-table.hh |  3 +--
+ src/hb-ot-shape-fallback.cc     |  9 +++++++++
+ src/hb-ot-shape.cc              | 12 +++++-------
+ 3 files changed, 15 insertions(+), 9 deletions(-)
+
+commit f4bad0086e40c70d66d6514f038ddda1411657c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:51:17 2018 -0500
+
+    [kerx] Implement tupleKerning for Format1
+
+    Untested.
+
+ src/hb-aat-layout-kerx-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 39b4ef6f18605e85c68cbcec534e137fc831dbca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:48:45 2018 -0500
+
+    [kerx] Better sanitize tupleKerning
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 14772da06f9c67d0d40712369e26064e3dee2a91
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:40:22 2018 -0500
+
+    [kern/kerx] Share KernTable, renamed to KerxTable
+
+ src/hb-aat-layout-kerx-table.hh |  77 ++++++++++++++++++++++--------
+ src/hb-ot-kern-table.hh         | 103
+ ++--------------------------------------
+ 2 files changed, 61 insertions(+), 119 deletions(-)
+
+commit c038f5be6b70b8edffc701dd3e4e3cd08d14e2f0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:35:06 2018 -0500
+
+    [fallback] Minor
+
+ src/hb-ot-shape-fallback.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit db6e658e8c0c4953c2f026f6a67a5d2fb4bdc204
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:33:23 2018 -0500
+
+    [kern/kerx] More towards sharing KernTable
+
+ src/hb-aat-layout-kerx-table.hh | 48 ++++++++++++++++++---------------
+ src/hb-ot-kern-table.hh         | 59
+ ++++++++++++++++++++++++++++-------------
+ 2 files changed, 67 insertions(+), 40 deletions(-)
+
+commit 89ec095979bde94bd203ed2c394f6e40629e9e78
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:10:05 2018 -0500
+
+    [kern] Disable Format1 and Format3 for OT-style tables
+
+ src/hb-ot-kern-table.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit ab57bcae0fd4505c80bb4ccdef6838bb2805ce79
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 13:04:21 2018 -0500
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 30af5b4a4c2071599dc87bc092a7329befcc45cc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:57:10 2018 -0500
+
+    [kern] Move code
+
+ src/hb-ot-kern-table.hh | 118
+ +++++++++++++++++++++++++-----------------------
+ 1 file changed, 62 insertions(+), 56 deletions(-)
+
+commit 1ff300464a1075b8cd5311970afbbcf4bb3b6f3d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:51:49 2018 -0500
+
+    [kern] Massage more
+
+ src/hb-ot-kern-table.hh | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+commit 8e9f6cd0fddd572e048487aae3141d3dbb1b99cb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:49:20 2018 -0500
+
+    [kerx] More minor
+
+ src/hb-aat-layout-kerx-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit f8c3df7d4a685bb86a1c15a5ef95485e8ef30305
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:48:06 2018 -0500
+
+    [kern/kerx] Minor
+
+ src/hb-aat-layout-kerx-table.hh |  5 +++--
+ src/hb-ot-kern-table.hh         | 19 ++++++++++---------
+ 2 files changed, 13 insertions(+), 11 deletions(-)
+
+commit f5e0a63a22f91720a997f5070b84e982e57de661
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:32:39 2018 -0500
+
+    [kern/kerx] Towards sharing KernTable
+
+ src/hb-aat-layout-kerx-table.hh |  4 ++--
+ src/hb-ot-kern-table.hh         | 19 +++++++------------
+ 2 files changed, 9 insertions(+), 14 deletions(-)
+
+commit 330508497d301c0ba5d5fb5d0900b62c191aabb5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:27:44 2018 -0500
+
+    [kern/kerx] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-ot-kern-table.hh         | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+commit 1a5ef8490034f4bd8965a3c71d34a5930ebe11b7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:19:52 2018 -0500
+
+    [kern/kerx] Share Format2
+
+    This, enables Format2 for kern table, which was disabled before.
+
+ src/hb-aat-layout-kerx-table.hh |  6 ++++
+ src/hb-ot-kern-table.hh         | 73
+ +----------------------------------------
+ 2 files changed, 7 insertions(+), 72 deletions(-)
+
+commit 8faec4e33486616fdc0d690ad80d4a38a73c8182
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:16:38 2018 -0500
+
+    [kerx] Towards merging Format2
+
+ src/hb-aat-layout-kerx-table.hh | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+commit ae8fd0dbfb57afadfe815c5bde4ad4a6485fd950
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 09:16:12 2018 -0800
+
+    clear stack after vsindex op
+
+ src/hb-cff2-interp-cs.hh | 1 +
+ src/hb-ot-cff2-table.hh  | 1 +
+ 2 files changed, 2 insertions(+)
+
+commit 7fed7d80f72b35900b41878ae59e38fd1cb49dc8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Nov 7 09:09:13 2018 -0800
+
+    fixed off-by-one error in CFF1 Encoding lookup
+
+ src/hb-ot-cff1-table.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit d5c0ca210fef315fd039e5b1825a865f36606a3f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 12:08:44 2018 -0500
+
+    [aat] Minor
+
+ src/hb-aat-layout-common.hh | 16 ++++++++++------
+ src/hb-ot-kern-table.hh     |  4 ++--
+ 2 files changed, 12 insertions(+), 8 deletions(-)
+
+commit e72e041c3cda164b2ffb02d770b35d0d70954818
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:56:36 2018 -0500
+
+    [kerx] Rename
+
+ src/hb-aat-layout-kerx-table.hh | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+commit 241ba7da518adee334fff105ae19dfb051868a57
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:51:40 2018 -0500
+
+    [morx/kerx] Rename types
+
+ src/hb-aat-layout-common.hh     |  4 ++--
+ src/hb-aat-layout-kerx-table.hh | 17 +++++++++--------
+ src/hb-aat-layout-morx-table.hh |  4 ++--
+ src/hb-ot-kern-table.hh         |  4 ++--
+ 4 files changed, 15 insertions(+), 14 deletions(-)
+
+commit c808e444da12840ac3ab1d78569504b9b7e876f9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:28:36 2018 -0500
+
+    [kern/kerx] Share Format1 subtable
+
+ src/hb-aat-layout-kerx-table.hh |   9 +-
+ src/hb-ot-kern-table.hh         | 187
+ +---------------------------------------
+ 2 files changed, 4 insertions(+), 192 deletions(-)
+
+commit a244190afa90ac253724a2ff23a3bdf0c507d0e6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:43:25 2018 -0500
+
+    [kerx] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 2a720911964a00ad607ff712be09ea3ea0925c9b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:25:55 2018 -0500
+
+    [kerx] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit f5f4ca7871ec2be2b5666a7b9e6e5e28133b8393
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:21:09 2018 -0500
+
+    [kern/kerx] Enable crossStream kerning in vertical
+
+    CoreText doesn't, but no reason we shouldn't do.
+
+ src/hb-aat-layout-kerx-table.hh | 8 ++++----
+ src/hb-ot-kern-table.hh         | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+commit d5c88af4a23bffc09840c43e6b1403b64a9f74d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:20:14 2018 -0500
+
+    [kerx] More towards sharing Format1
+
+ src/hb-aat-layout-kerx-table.hh | 35 +++++++++++++++++++++++++++++++----
+ src/hb-aat-layout-morx-table.hh | 10 ++++++----
+ 2 files changed, 37 insertions(+), 8 deletions(-)
+
+commit b693fd0dc6c7979dcacdff060ecf12a2e107071d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:05:28 2018 -0500
+
+    [morx] Simplify
+
+ src/hb-aat-layout-morx-table.hh | 27 +++++++++++----------------
+ 1 file changed, 11 insertions(+), 16 deletions(-)
+
+commit ce3451dc2aad2241c148953842e696e9f53b5deb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 11:02:04 2018 -0500
+
+    [kerx] Towards sharing Format1
+
+ src/hb-aat-layout-kerx-table.hh | 61
+ +++++++++++++++++++++++++++++++----------
+ 1 file changed, 47 insertions(+), 14 deletions(-)
+
+commit e890753ebbf0d20c1c86796837918d530610df3b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:58:50 2018 -0500
+
+    [morx] Minor
+
+ src/hb-aat-layout-morx-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 5b17853547ca6848ee652ef6990a81bb345ac06f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:45:25 2018 -0500
+
+    [kern/kerx] Share Format0
+
+ src/hb-aat-layout-kerx-table.hh | 22 +++++++++++++-----
+ src/hb-ot-kern-table.hh         | 50
+ ++++++-----------------------------------
+ 2 files changed, 23 insertions(+), 49 deletions(-)
+
+commit c97dde5d55929df394fbe57c1ba1a725592c6732
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:39:39 2018 -0500
+
+    [kern/kerx] Towards merge more
+
+ src/hb-aat-layout-kerx-table.hh | 75
+ ++++++++++++++++++++++++++++++-----------
+ src/hb-kern.hh                  | 33 ------------------
+ src/hb-ot-kern-table.hh         |  7 ++--
+ 3 files changed, 58 insertions(+), 57 deletions(-)
+
+commit 540ccc38b0f95804d08047f8b2d059bfd1e09337
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:33:46 2018 -0500
+
+    [kern/kerx] More towards sharing
+
+ src/hb-aat-layout-kerx-table.hh |  7 ++++---
+ src/hb-ot-kern-table.hh         | 10 +++++++---
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+commit d0f8f4c200670bc0bfbffbf301139a3613865a7f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:25:25 2018 -0500
+
+    [kern] Move kern machine to hb-kern.hh
+
+ src/Makefile.sources            |   1 +
+ src/hb-aat-layout-kerx-table.hh |   5 +-
+ src/hb-kern.hh                  | 153
+ ++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-kern-table.hh         | 115 +-----------------------------
+ src/hb-ot-shape-fallback.cc     |   2 +-
+ 5 files changed, 157 insertions(+), 119 deletions(-)
+
+commit a6acff252c72457ecfa856fd6c57081b3a4290dd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 10:19:46 2018 -0500
+
+    [kerx] Towards sharing subtables with kern
+
+ src/hb-aat-layout-kerx-table.hh | 41
+ +++++++++++++++++++++++------------------
+ 1 file changed, 23 insertions(+), 18 deletions(-)
+
+commit befac337ca2c705e2cea60a9a92e40e0dbbc40aa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 09:53:02 2018 -0500
+
+    [kern] Remove Override business
+
+    Not used in any fonts.  Not well-specified when mixing kerning with
+    Cross-Stream positioning.
+
+ src/hb-ot-kern-table.hh | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+commit 9d5027696e418b7c2a5ccbc18faafe6b9290d08b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 09:16:53 2018 -0500
+
+    [post] Return true on truncation
+
+    Client can check that buffer was completely filled out and reallocate.
+
+ src/hb-ot-post-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 7d91f07edf29c4923716af6cee8eb94f948ac91f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 09:14:42 2018 -0500
+
+    [post] Protect against huge empty tables
+
+ src/hb-ot-post-table.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 5ed816ab5900ac4ff7feca3d98cbd92e62fd1754
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 09:13:51 2018 -0500
+
+    [post] Minor
+
+ src/hb-ot-post-table.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 64f0becd89cc2b0136c7dc1609abc9f957525cf8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 09:10:55 2018 -0500
+
+    [post] Fix bound checking
+
+ src/hb-ot-post-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7ec694ddf25a313483044256f7ed88b644432e15
+Author: HinTak <htl10@users.sourceforge.net>
+Date:   Wed Nov 7 13:19:36 2018 +0000
+
+    Use non-GRID-fitted values for metrics (#1363)
+
+    * Use non-GRID-fitted values for metrics
+
+    See freetype/src/base/ftobjs.c:ft_recompute_scaled_metrics() and
+    the usage of GRID_FIT_METRICS inside.
+
+    Fixes https://github.com/behdad/harfbuzz/issues/1262
+
+    * Update hb-ft.cc
+
+ src/hb-ft.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 59e04e42312293c30714a666c4479e209aec3c0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 00:25:48 2018 -0500
+
+    [kern/kerx] Fix cursive joining
+
+    Tested with Waseem TTC:
+
+    $ hb-shape Waseem.ttc جحخج
+    [F1Jeem_R2=3@0,180+479|M1Khah_L2_R2=2@0,682+403|M1Hah_L2_R2=1@0,1184+403|I1Jeem_L2=0@0,1184+744]
+
+ src/hb-aat-layout-kerx-table.hh | 2 ++
+ src/hb-ot-kern-table.hh         | 2 ++
+ 2 files changed, 4 insertions(+)
+
+commit 8d0f797139e853d13cb2383d541c2e691d9dbae3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Nov 7 00:04:40 2018 -0500
+
+    [kern/kerx] Fix "reset" magic value
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-ot-kern-table.hh         | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 0123976a0c1e2f629252969a7ff632dc2b1dbbc9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 21:45:40 2018 -0500
+
+    [kerx] Adjust CrossStream kern to match 'kern' table
+
+ src/hb-aat-layout-kerx-table.hh | 62
+ +++++++++++++++++++++++++++++++----------
+ 1 file changed, 48 insertions(+), 14 deletions(-)
+
+commit 80a33b9ac351d81793f35a92e0255ffbf5ceb8b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 21:41:28 2018 -0500
+
+    [kern] More tweaks
+
+    Solves a mystery or two.  I'm fairly confident this is what CoreText
+    does now.
+
+ src/hb-ot-kern-table.hh | 40 ++++++++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 18 deletions(-)
+
+commit 564e8ac0465d8ced3a98ecb55d09ffaa45eefc2f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 21:04:40 2018 -0500
+
+    [kern] Adjust some more
+
+    Getting closer.  So many open questions still...
+
+ src/hb-ot-kern-table.hh | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+commit 4d003b8503f9c984abe2ac0de8c526a276ea8e54
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 21:04:02 2018 -0500
+
+    [kern] Add TODO
+
+ src/hb-ot-kern-table.hh | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 9810f0b80e5b6580a7a15debcec073dfc9ca759f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 19:24:04 2018 -0500
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9c04b6058306cd4b2123a33a7cbeb47505434217
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 18:35:58 2018 -0500
+
+    [kern] In Format1, adjust how kerning is done
+
+    In a series of kerns in one action, kern all but last glyph forward,
+    and the last one backward.  Seems to better match what CoreText
+    is doing.
+
+    Test cases, with GeezaPro Arabic:
+
+    $ ./hb-shape GeezaPro_10_10.ttc -u U+0631,U+0628
+    [u0628.beh=1+1415|u0631.reh=0@-202,0+700]
+
+    $ ./hb-shape GeezaPro_10_10.ttc -u U+0628,U+064F
+    [u064f.damma=0@0,-250+-250|u0628.beh=0@250,0+1665]
+
+    In a later change, I'll make kern machine avoid producing negative
+    kerns.
+
+ src/hb-ot-kern-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e8c47724638c29d78001905610c662de99c59cad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 17:16:04 2018 -0500
+
+    [kern] XXX Negate CrossKerning sign
+
+    Not sure why, but seems to better match GeezaPro Arabic w CoreText.
+
+    Quite possibly I'm doing something very wrong...
+
+ src/hb-ot-kern-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 01bf43ac01576a6415336cc56c74bb1a872566d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 14:48:42 2018 -0500
+
+    [kern] Implement CrossStream kerning
+
+ src/hb-aat-layout-kerx-table.hh | 75
+ ++++++++++++++++++++++++++---------------
+ src/hb-ot-kern-table.hh         | 63 ++++++++++++++++++++++++++++------
+ 2 files changed, 101 insertions(+), 37 deletions(-)
+
+commit b11830c09e0d78bbdaf86ef02191d00b3d8256c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 15:23:18 2018 -0500
+
+    [kern] Improve Format 2
+
+    Still disabled.
+
+ src/hb-aat-layout-common.hh | 20 +++++++++-----------
+ src/hb-ot-kern-table.hh     | 35 ++++++-----------------------------
+ 2 files changed, 15 insertions(+), 40 deletions(-)
+
+commit c0383c6bb725bed2a48485988a427348384f3f87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 15:07:19 2018 -0500
+
+    Minor
+
+ src/hb-aat-layout-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 10e6f708f30986bab9f7b506935f2555d6b79ff4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 13:32:13 2018 -0500
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 30 +++++++++++-------------------
+ 1 file changed, 11 insertions(+), 19 deletions(-)
+
+commit 164eedd9181345d84d5f8059475ad4b97784fd46
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 13:18:27 2018 -0500
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+commit 220a5991baa213b7bd173ea02090dc6fc8aef655
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 13:51:39 2018 -0500
+
+    [kern/kerx] Fix trace numbering
+
+ src/hb-aat-layout-kerx-table.hh | 1 +
+ src/hb-ot-kern-table.hh         | 1 +
+ 2 files changed, 2 insertions(+)
+
+commit 7b21319edfd6531a444846f71e87303bc09f4621
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Nov 6 13:59:07 2018 -0800
+
+    don't reject empty Dict
+
+ src/hb-cff-interp-dict-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 43ee0e4d006ce7b4ade4483f2c8ec3d39723fc94
+Merge: ec6817c1 bfafe208
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Nov 6 09:57:17 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit bfafe208da11817b5ebf3751f02af2dcdf57bd19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 12:11:45 2018 -0500
+
+    [kern] Switch to dispatch
+
+ src/hb-aat-layout-kerx-table.hh | 12 ++++++------
+ src/hb-ot-kern-table.hh         | 31 +++++++++++++++----------------
+ 2 files changed, 21 insertions(+), 22 deletions(-)
+
+commit 213fa3bf711dae5028e3d041e305cdd35223de77
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 12:07:15 2018 -0500
+
+    [kern] Refactor to include header in each subtable type
+
+ src/hb-ot-kern-table.hh | 189
+ +++++++++++++++++++++++-------------------------
+ 1 file changed, 91 insertions(+), 98 deletions(-)
+
+commit b0da2cd0b9c1346b7cda5997fb799e895e34aace
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 11:16:45 2018 -0500
+
+    [kern] Some more
+
+ src/hb-ot-kern-table.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 75b00b51c8fca5d605c479333eb3abd608623613
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 11:13:40 2018 -0500
+
+    [kern] Renames
+
+ src/hb-ot-kern-table.hh | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+commit 5c3ccbc634158ba9f84d365c9a31a596f6d8825b
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Tue Nov 6 18:10:56 2018 +0200
+
+    Another missing backlash
+
+    Did this ever work?
+
+ test/api/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d29602b962c13836f4c0d46796bc693f66f9b9fe
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Tue Nov 6 18:07:47 2018 +0200
+
+    Add missing backslash
+
+ test/api/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9bddfde25dc8c302c765a1e9a8a2c38c4a836e2e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 11:03:34 2018 -0500
+
+    [util] Fix up previous commit
+
+ util/options.cc | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 3ec2e4fa7bec07ec181a0390e5f5fd695abee611
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 10:49:19 2018 -0500
+
+    [util] Don't terminate string after a a 0 in -u
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1361
+
+ util/options.cc | 4 +++-
+ util/options.hh | 2 ++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit 8790b2740a334f1789fb0cf329f2b8ac9733793c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 10:24:54 2018 -0500
+
+    [fuzzing] Fix test
+
+ test/fuzzing/hb-shape-fuzzer.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 3af0a7edd0c99aaef846ae787056d7664bc69d35
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 10:20:57 2018 -0500
+
+    [fuzzing] Add make check-valgrind
+
+ test/fuzzing/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit b062378ce640eb418cb413b595b79cc81a193209
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 10:20:36 2018 -0500
+
+    [test] Minor
+
+ test/api/.valgrind-suppressions | 0
+ test/api/Makefile.am            | 2 +-
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 37f421c951c853dff165df6731d0ab9c46350790
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Nov 6 10:03:38 2018 -0500
+
+    Minor
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b6112e5ea4d08fcbfa8f7cb4ef3903514a6e99f3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Nov 6 11:42:47 2018 +0330
+
+    [test] Fix -Weverything bot complain
+
+ test/api/test-ot-name.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a49df419f04b4065fc7f70a77c5cbc453e6ba906
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Nov 6 11:26:30 2018 +0330
+
+    [test] Test hb_ot_name_{list_names,get_utf8} on test-ot-name
+
+ test/api/test-ot-name.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+commit 9139cc23ea9fb339be9426860e0c72038d32a2ab
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Nov 6 11:17:14 2018 +0330
+
+    Fix link issue of some of the bots
+
+    e.g. https://circleci.com/gh/harfbuzz/harfbuzz/52410
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 98b37f0c109d0f7454e91c9563c56d1903d6d496
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Nov 6 09:16:28 2018 +0330
+
+    [mort] Fix table detection logic
+
+    mort really needs some initial tests at least.
+
+ src/hb-aat-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fa3ebf845fcffa827600fc4ca9fdde3aaa99f4c5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:34:07 2018 -0500
+
+    Simplify some more
+
+ src/hb-aat-layout.cc | 10 +++++-----
+ src/hb-ot-layout.cc  |  2 +-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit 61f52231f430c72e1b66b76dabb018cfe45a01d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:28:52 2018 -0500
+
+    [math] Shorten names a bit
+
+ src/hb-ot-math-table.hh |  4 ++--
+ src/hb-ot-math.cc       | 33 +++++++++++++++++++--------------
+ 2 files changed, 21 insertions(+), 16 deletions(-)
+
+commit 737efbe65583a71d7df9ae7b423d9fb1d68599b7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:26:29 2018 -0500
+
+    [ot-layout] Simplify GSUB/GPOS access
+
+    This concludes simplifying table access to face->table.XXXX.
+
+ src/hb-ot-layout.cc | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+commit 5e68cec17913e9f6e98e5017a56c78a5614e4030
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:23:57 2018 -0500
+
+    [ot-layout] Simplify GDEF access
+
+ src/hb-ot-layout.cc | 44 ++++++++++++++++----------------------------
+ 1 file changed, 16 insertions(+), 28 deletions(-)
+
+commit 33b006cc51b0d27cbe1d8ed498bbf2b548cb6554
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:19:04 2018 -0500
+
+    [ot-layout] Simplify some access
+
+ src/hb-ot-layout-gdef-table.hh |  2 +-
+ src/hb-ot-layout-gpos-table.hh |  9 +++++----
+ src/hb-ot-layout-gsub-table.hh |  9 +++++----
+ src/hb-ot-layout-gsubgpos.hh   |  2 +-
+ src/hb-ot-layout.hh            | 12 +-----------
+ 5 files changed, 13 insertions(+), 21 deletions(-)
+
+commit db35409f0db9faf91a10defc81e4d6d60dc7822a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:11:46 2018 -0500
+
+    [ot-layout] Remove ensures
+
+ src/hb-ot-layout.cc | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+commit 9198de7b9b6020c1e3d6a48783e36db7e1f7e99a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:10:37 2018 -0500
+
+    [ot-font] Remove ensure
+
+ src/hb-ot-font.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit ea6d9b661fc3cf6bc4366feeb7694c0b712abfae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:09:29 2018 -0500
+
+    [ot-face] Remove a few ensures
+
+ src/hb-face.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 0fe7a745c9a323a3fc76beb011b6ab8919cf905b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 23:08:33 2018 -0500
+
+    [ot-face] Simplify more table access
+
+ src/hb-face.cc      |  6 +++---
+ src/hb-ot-face.hh   |  3 ---
+ src/hb-ot-font.cc   |  4 +---
+ src/hb-ot-layout.cc | 34 +++++++++++++++++-----------------
+ 4 files changed, 21 insertions(+), 26 deletions(-)
+
+commit a35c92cbe771a75df40412fd248ad06f6a0cfebf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 22:58:43 2018 -0500
+
+    [ot-face] Simplify table access
+
+    Yoohoo!
+
+ src/hb-aat-layout.cc | 107
+ ++++++++++-----------------------------------------
+ src/hb-ot-color.cc   |  66 ++++++++-----------------------
+ src/hb-ot-layout.cc  |  20 ++--------
+ src/hb-ot-math.cc    |  47 ++++++++--------------
+ src/hb-ot-name.cc    |  11 +-----
+ src/hb-ot-var.cc     |  33 ++++------------
+ 6 files changed, 64 insertions(+), 220 deletions(-)
+
+commit 914b595f2598d5bdb2c750832d567a57d45db84e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 22:39:50 2018 -0500
+
+    [ot-face] Include hb-ot-face directly in hb_face_t
+
+    Simplifying access coming next.
+
+ src/hb-face.cc     |  4 ++++
+ src/hb-face.hh     |  3 +++
+ src/hb-ot-face.cc  | 24 ++----------------------
+ src/hb-ot-face.hh  | 39 +++++++++++++++------------------------
+ src/hb-ot-font.cc  | 24 ++++++++++++------------
+ src/hb-ot-math.cc  |  3 +--
+ src/hb-ot-shape.cc |  5 +++--
+ 7 files changed, 40 insertions(+), 62 deletions(-)
+
+commit 56ba998cddbb2ba5d24fb0b02d2bf77a46c0f23f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 19:49:54 2018 -0500
+
+    [cmap] Push get_nominal_glyphs down into cmap accelerator
+
+ src/hb-ot-cmap-table.hh | 21 +++++++++++++++++++++
+ src/hb-ot-font.cc       | 13 +++----------
+ 2 files changed, 24 insertions(+), 10 deletions(-)
+
+commit 36d85dce25abd079252d973f804220bf7b97e987
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 19:46:29 2018 -0500
+
+    [cmap] Use hb_nonnullptr_t
+
+ src/hb-ot-cmap-table.hh | 34 ++++++++++++++--------------------
+ 1 file changed, 14 insertions(+), 20 deletions(-)
+
+commit 8be74d85534534dbdd39a0a6f496e26e9f3e661d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 18:47:22 2018 -0500
+
+    2.1.1
+
+ NEWS             | 8 ++++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+commit 6482fda519ca7d173e3bcb3717aa30e237f04b25
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 15:03:18 2018 -0500
+
+    [fuzzing] Fuzz glyph-id etc in test-ot-face
+
+ test/api/test-ot-face.c         | 57
+ +++++++++++++++++++++--------------------
+ test/fuzzing/hb-shape-fuzzer.cc | 19 +-------------
+ 2 files changed, 30 insertions(+), 46 deletions(-)
+
+commit 252632c477b963f305116d69fcafacd8bf7b97bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 14:33:41 2018 -0500
+
+    [uniscribe] Fix use of deprecated API
+
+ src/hb-uniscribe.cc | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit bb380ec18394b2c581b672ecbf98991e14897f2e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 13:45:12 2018 -0500
+
+    [cmap] Make null accelerator safe
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1146
+
+ src/hb-ot-cmap-table.hh | 50
+ ++++++++++++++++++++++++-------------------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+commit f6fc5574d3dae177a54b10195e0d1f368a74f768
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 13:23:54 2018 -0500
+
+    Add pointer magic operators to hb_atomic_ptr_t
+
+ src/hb-atomic.hh                  | 3 +++
+ src/hb-common.cc                  | 6 +++---
+ src/hb-face.cc                    | 2 +-
+ src/hb-graphite2.cc               | 8 ++++----
+ src/hb-machinery.hh               | 1 +
+ src/hb-ot-shape-complex-arabic.cc | 4 ++--
+ src/hb-shape-plan.cc              | 2 +-
+ 7 files changed, 15 insertions(+), 11 deletions(-)
+
+commit f6e7cb51b13aabb447dc97a59602d65eb42edc4b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 13:23:07 2018 -0500
+
+    Fix const-confusion in hb_array_t as well
+
+ src/hb-dsalgs.hh | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 0da22fb0ada8a54fc59739057f281a406a993212
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 13:13:39 2018 -0500
+
+    [null] Tweak hb_nonnull_ptr_t some more
+
+ src/hb-null.hh | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+commit 03348ce0051cfae7172ac0d09b83ed5f82fa842a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Nov 5 12:59:32 2018 -0500
+
+    Minor
+
+ src/hb-aat-layout.cc | 12 ++++++------
+ src/hb-ot-color.cc   | 10 +++++-----
+ src/hb-ot-font.cc    | 18 +++++++++---------
+ src/hb-ot-layout.cc  |  2 +-
+ src/hb-ot-math.cc    |  2 +-
+ src/hb-ot-name.cc    |  2 +-
+ src/hb-ot-var.cc     |  6 ++----
+ 7 files changed, 25 insertions(+), 27 deletions(-)
+
+commit ec6817c1bd82a60b84cb868e4d7ff4c65cb80ccc
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Nov 5 07:59:08 2018 -0800
+
+    remove build files accidentally pushed
+
+ INSTALL                 |   370 -
+ Makefile                |   954 --
+ Makefile.in             |   954 --
+ aclocal.m4              |  1496 ---
+ ar-lib                  |   270 -
+ autom4te.cache/output.0 | 23333
+ ----------------------------------------------
+ autom4te.cache/output.1 | 23333
+ ----------------------------------------------
+ autom4te.cache/output.2 | 23333
+ ----------------------------------------------
+ autom4te.cache/requests |   555 --
+ autom4te.cache/traces.0 |  3823 --------
+ autom4te.cache/traces.1 |  1229 ---
+ autom4te.cache/traces.2 |  3823 --------
+ compile                 |   347 -
+ config.guess            |  1421 ---
+ config.h                |   227 -
+ config.h.in             |   226 -
+ config.log              |  1560 ----
+ config.status           |  2420 -----
+ config.sub              |  1807 ----
+ configure               | 23333
+ ----------------------------------------------
+ depcomp                 |   791 --
+ install-sh              |   501 -
+ libtool                 | 11805 -----------------------
+ ltmain.sh               | 11147 ----------------------
+ missing                 |   215 -
+ stamp-h1                |     1 -
+ test-driver             |   148 -
+ 27 files changed, 139422 deletions(-)
+
+commit b721fdae662673ab706da897aaa1db126f8ca1a5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sun Nov 4 16:19:15 2018 -0800
+
+    fixed leaks in CFF subr subset
+
+ src/hb-ot-cff-common.hh     | 10 +++++++++-
+ src/hb-subset-cff-common.hh | 10 +++++++++-
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+commit 85f5644e8e9fe18032e37d4153c3c928d087ac6a
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sun Nov 4 14:17:30 2018 -0800
+
+    added missing switch breaks
+
+ src/hb-subset-cff-common.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 1682d1bbecaeeddc8a1678a01c57c0e0023bf7c4
+Merge: d8fadec0 b605db2f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sun Nov 4 13:25:41 2018 -0800
+
+    Merge branch 'master' into cff-subset
+
+commit d8fadec098935335e69e46c1101da3f142824638
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sun Nov 4 13:12:20 2018 -0800
+
+    added desubroutinize full font test profiles & expected fonts
+
+    modified subset_test_suite.py to apply desubroutinize profiles to
+    CFF only (not to TT)
+
+ ...urceSansPro-Regular.default.1FC,21,41,20,62,63.otf | Bin 3640 ->
+ 3784 bytes
+ .../SourceSansPro-Regular.default.61,62,63.otf        | Bin 3400 ->
+ 3496 bytes
+ .../SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf  | Bin 3596 ->
+ 3612 bytes
+ ...sPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf | Bin 0 ->
+ 3640 bytes
+ .../SourceSansPro-Regular.desubroutinize.61,62,63.otf | Bin 0 ->
+ 3400 bytes
+ ...eSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf | Bin 0 ->
+ 3596 bytes
+ ...eSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 3480 ->
+ 3564 bytes
+ .../SourceSansPro-Regular.drop-hints.61,62,63.otf     | Bin 3276 ->
+ 3340 bytes
+ ...ourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf | Bin 3448 ->
+ 3464 bytes
+ ...r.drop-hints.desubroutinize.1FC,21,41,20,62,63.otf | Bin 0 ->
+ 3480 bytes
+ ...Pro-Regular.drop-hints.desubroutinize.61,62,63.otf | Bin 0 ->
+ 3276 bytes
+ ...gular.drop-hints.desubroutinize.D7,D8,D9,DA,DE.otf | Bin 0 ->
+ 3448 bytes
+ ...-Regular.default.3042,3044,3046,3048,304A,304B.otf | Bin 6248 ->
+ 6324 bytes
+ ...-Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 6432 ->
+ 6568 bytes
+ .../SourceHanSans-Regular.default.61,63,65,6B.otf     | Bin 5428 ->
+ 5500 bytes
+ ...-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 6552 ->
+ 6780 bytes
+ .../japanese/SourceHanSans-Regular.default.660E.otf   | Bin 5196 ->
+ 5248 bytes
+ ....otf => SourceHanSans-Regular.desubroutinize..otf} | Bin
+ ...r.desubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 0 ->
+ 6248 bytes
+ ...r.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 0 ->
+ 6432 bytes
+ ...urceHanSans-Regular.desubroutinize.61,63,65,6B.otf | Bin 0 ->
+ 5428 bytes
+ ...r.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 0 ->
+ 6552 bytes
+ .../SourceHanSans-Regular.desubroutinize.660E.otf     | Bin 0 ->
+ 5196 bytes
+ ...gular.drop-hints.3042,3044,3046,3048,304A,304B.otf | Bin 6076 ->
+ 6132 bytes
+ ...gular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 6180 ->
+ 6304 bytes
+ .../SourceHanSans-Regular.drop-hints.61,63,65,6B.otf  | Bin 5312 ->
+ 5344 bytes
+ ...gular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 6248 ->
+ 6472 bytes
+ .../SourceHanSans-Regular.drop-hints.660E.otf         | Bin 5088 ->
+ 5140 bytes
+ ...rceHanSans-Regular.drop-hints.desubroutinize..otf} | Bin
+ ...s.desubroutinize.3042,3044,3046,3048,304A,304B.otf | Bin 0 ->
+ 6076 bytes
+ ...s.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 0 ->
+ 6180 bytes
+ ...-Regular.drop-hints.desubroutinize.61,63,65,6B.otf | Bin 0 ->
+ 5312 bytes
+ ...s.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 0 ->
+ 6248 bytes
+ ...HanSans-Regular.drop-hints.desubroutinize.660E.otf | Bin 0 ->
+ 5140 bytes
+ test/subset/data/profiles/desubroutinize.txt          |   1 +
+ .../data/profiles/drop-hints-desubroutinize.txt       |   2 ++
+ test/subset/generate-expected-outputs.py              |   1 -
+ test/subset/subset_test_suite.py                      |   7 ++++++-
+ 38 files changed, 9 insertions(+), 2 deletions(-)
+
+commit b605db2f65e62ad6727a61481f78015933dbf207
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 4 12:58:02 2018 -0500
+
+    [aat] Clean up ankr table include mess
+
+ src/hb-aat-layout-ankr-table.hh |  2 ++
+ src/hb-aat-layout-common.hh     | 31 +++++++++---------------------
+ src/hb-aat-layout-kerx-table.hh | 16 ++++++++--------
+ src/hb-aat-layout.cc            | 42
+ +++++++++++++++++++++++++++++++++++++++--
+ src/hb-ot-kern-table.hh         |  1 -
+ src/hb-static.cc                |  1 -
+ 6 files changed, 59 insertions(+), 34 deletions(-)
+
+commit bce437cf0b71e9b60bbf058eaf61593fed30ae33
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 4 02:47:34 2018 -0500
+
+    [test] Call test-ot-face.c test from hb-shape-fuzzer
+
+    Should increase coverage...
+
+ test/api/test-ot-face.c         | 28 ++++++++++++++++++----------
+ test/fuzzing/hb-shape-fuzzer.cc |  6 ++++++
+ 2 files changed, 24 insertions(+), 10 deletions(-)
+
+commit 777c22425cae97009ca4dc5b1e400670c4aa0799
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 4 02:40:20 2018 -0500
+
+    [test] More funcs in test-ot-face
+
+ test/api/test-font.c    |  5 +++++
+ test/api/test-ot-face.c | 21 +++++++++++++++++++--
+ 2 files changed, 24 insertions(+), 2 deletions(-)
+
+commit 17335a8161e674e630287e18a6d304ec0c33767c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Nov 4 02:25:07 2018 -0500
+
+    Clean up buffer->swap_buffers() calls
+
+    That function checks for buffer->successful already.  No need
+    to check at call site.
+
+ src/gen-vowel-constraints.py                 | 4 +---
+ src/hb-aat-layout-common.hh                  | 3 +--
+ src/hb-aat-layout-morx-table.hh              | 3 +--
+ src/hb-ot-shape-complex-indic.cc             | 1 -
+ src/hb-ot-shape-complex-khmer.cc             | 1 -
+ src/hb-ot-shape-complex-myanmar.cc           | 1 -
+ src/hb-ot-shape-complex-thai.cc              | 3 +--
+ src/hb-ot-shape-complex-use.cc               | 1 -
+ src/hb-ot-shape-complex-vowel-constraints.cc | 5 ++---
+ src/hb-ot-shape.cc                           | 1 -
+ 10 files changed, 6 insertions(+), 17 deletions(-)
+
+commit 191ca0f15b7fc9ab959e1f6472c48839687402ec
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Nov 3 22:42:22 2018 -0700
+
+    CFF1 no-desubr fixes
+
+    make sure charstring/subrs not ending with endchar/return handled
+    correctly
+    if no local subrs, skip serializing Subrs op in Private
+    misc fixes
+
+ src/hb-ot-cff-common.hh     | 13 +++++++++-
+ src/hb-subset-cff-common.hh | 59
+ +++++++++++++++++++++++----------------------
+ src/hb-subset-cff1.cc       | 27 +++++++++++++++------
+ 3 files changed, 62 insertions(+), 37 deletions(-)
+
+commit 4eb52460c8c6dc48af240f2254f76fae065bfa97
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 21:45:39 2018 -0400
+
+    Fix >>
+
+ src/hb-ot-post-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ae9ad1076e536aee370f9863cde8351b79f01b3b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 21:41:50 2018 -0400
+
+    Fix "Warning: extra ";" ignored."
+
+ src/hb.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit d0163afb7bed83935c6a54d57a0e7366caeba0b3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 21:38:24 2018 -0400
+
+    Revert "Add operator char * to the naked array types as well"
+
+    This reverts commit db889c182ee5f54127285bfaab5bc94dafe46bda.
+
+    Was resulting in ambigious overloads...
+
+ src/hb-dsalgs.hh    | 4 +---
+ src/hb-open-type.hh | 2 --
+ 2 files changed, 1 insertion(+), 5 deletions(-)
+
+commit c8f94a1ca6928f07749285da910b63087d485537
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 21:07:39 2018 -0400
+
+    Minor
+
+ src/hb-ot-name.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9779e602ed7ac214c0da2c90e104b38460422476
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 20:50:56 2018 -0400
+
+    [test] Add test for empty face
+
+ test/api/Makefile.am    |  1 +
+ test/api/test-ot-face.c | 94
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 95 insertions(+)
+
+commit 1da4de7e7b71dfde734cb77ec6acb31f574585f2
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Nov 3 15:41:29 2018 -0700
+
+    fix for subset fuzzer failure
+
+    A called subr must be freshly parsed or completely parsed. otherwise
+    the prevoius parse must have terminated prematurely
+
+ src/hb-subset-cff1.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 0b0b38ec1e6a815a30bef98193043d255b52c4a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 16:15:30 2018 -0400
+
+    Fix null accelerator's
+
+    Fixes all except for cmap.  To be done separately.
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1146
+
+ src/hb-ot-color-cbdt-table.hh  | 10 ++--------
+ src/hb-ot-color-sbix-table.hh  | 11 ++++-------
+ src/hb-ot-color-svg-table.hh   | 11 ++++-------
+ src/hb-ot-glyf-table.hh        |  6 +++---
+ src/hb-ot-layout-gdef-table.hh |  2 +-
+ src/hb-ot-layout-gsubgpos.hh   |  2 +-
+ src/hb-ot-name-table.hh        |  2 +-
+ src/hb-ot-post-table.hh        |  2 +-
+ 8 files changed, 17 insertions(+), 29 deletions(-)
+
+commit db889c182ee5f54127285bfaab5bc94dafe46bda
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 16:04:19 2018 -0400
+
+    Add operator char * to the naked array types as well
+
+ src/hb-dsalgs.hh    | 4 +++-
+ src/hb-open-type.hh | 2 ++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit d6fdae310f2a98ca624c3a77c3aa03b8b3bd393a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 16:02:03 2018 -0400
+
+    Add operator char * to hb_nonnull_ptr_t
+
+ src/hb-null.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 7430ff604aa54bedcb07cc1c2962eae85fcade76
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:59:13 2018 -0400
+
+    Template casts in hb_nonnull_ptr_t
+
+ src/hb-null.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit da408fce98153e0fab3d82fe28813085feed0974
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:49:37 2018 -0400
+
+    [blob] Allow null parent in create_sub_blob()
+
+    Like font and unicode.
+
+ src/hb-blob.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fb0f30f55a5d654b2f1f9b99efa9b8abc51dbf34
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:24:14 2018 -0400
+
+    Add hb_nonnull_ptr_t
+
+    Towards fixing https://github.com/harfbuzz/harfbuzz/issues/1146
+
+ src/hb-null.hh | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+commit 8d98c51d133b058a845ed7a84bfe8a43083bbb03
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:14:57 2018 -0400
+
+    [kern] Third try fix access violation in Format3
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11245
+
+ src/hb-ot-kern-table.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit f074da8c2b6a7061c71d12213a6c494c119eb20e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:06:45 2018 -0400
+
+    [kern] Really fix access violation in Format3
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11245
+
+ src/hb-ot-kern-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 93ef20a83b31e6528bb1835d2b4b83b913805885
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 15:03:06 2018 -0400
+
+    Replace most uses of is_inert with is_immutable
+
+ src/hb-buffer.cc     | 32 ++++++++++++++++----------------
+ src/hb-coretext.cc   |  2 +-
+ src/hb-font.cc       |  2 +-
+ src/hb-set.hh        |  8 +++++---
+ src/hb-shape-plan.cc |  2 +-
+ 5 files changed, 24 insertions(+), 22 deletions(-)
+
+commit 0589787ff55bff9bd5849c4443229e926cc574a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 14:58:54 2018 -0400
+
+    [kern] Fix access violation in Format3
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11245
+
+ src/hb-ot-kern-table.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 5570c87f21f061cc197e02bd0526ab44c63ed6f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 14:51:38 2018 -0400
+
+    Port objects to use header.writable instead of immutable
+
+    Saves 4 or 8 bytes per object on 64bit archs.
+
+ src/hb-blob.cc    | 12 ++++--------
+ src/hb-blob.hh    |  2 --
+ src/hb-face.cc    | 16 ++++++----------
+ src/hb-face.hh    |  2 --
+ src/hb-font.cc    | 46 +++++++++++++++++++---------------------------
+ src/hb-font.hh    |  4 ----
+ src/hb-ft.cc      |  2 +-
+ src/hb-object.hh  | 11 ++++++++---
+ src/hb-unicode.cc | 11 ++++-------
+ src/hb-unicode.hh |  2 --
+ 10 files changed, 42 insertions(+), 66 deletions(-)
+
+commit ee351a38ec0c62b76dd1b3f20fe56cb4d63e62be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Nov 3 14:28:55 2018 -0400
+
+    [object] Add "writable"
+
+ src/hb-object.hh | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+commit b8a78ce201608e9ac6d7f77447b2bbef6f09e9ff
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 3 22:28:30 2018 +0330
+
+    [BASE] Improvements (#1347)
+
+ src/hb-ot-layout-base-table.hh | 610
+ ++++++++++++++++++-----------------------
+ src/hb-ot-layout.cc            |  65 ++++-
+ src/hb-ot-layout.h             |  16 --
+ test/api/Makefile.am           |   1 +
+ test/api/fonts/base.ttf        | Bin 0 -> 5596 bytes
+ test/api/test-baseline.c       |  58 ++++
+ 6 files changed, 380 insertions(+), 370 deletions(-)
+
+commit c560ca92512c0283e826c059431273ffecf5d993
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Nov 3 13:03:36 2018 +0330
+
+    [fuzz] A new testcase
+
+ ...uzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 | Bin 0 ->
+ 36 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 34b06d994a79124963d2a7432d0ec945e72bfdbd
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 2 16:40:20 2018 -0700
+
+    fixed FDSelect size calcluation
+
+ src/hb-ot-cff-common.hh                               |   2 +-
+ src/hb-subset-cff-common.cc                           |   6 +++---
+ test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf | Bin 2576 ->
+ 3892 bytes
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 481fdfdc23f557400ad3aceeceeab07add78f005
+Merge: 1bc710a8 2840a104
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 2 15:28:09 2018 -0700
+
+    Merge branch 'cff-subset' of https://github.com/harfbuzz/harfbuzz
+    into cff-subset
+
+commit 1bc710a8c94fbe08ca3a3e535c7b6597a57883df
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Nov 2 15:28:01 2018 -0700
+
+    added CFF1 desubr api test cases & bug fixes
+
+ src/hb-cff1-interp-cs.hh                           |   7 --
+ src/hb-ot-cff-common.hh                            |  56 ++++++----
+ src/hb-subset-cff-common.hh                        | 100
+ +++++++++--------
+ src/hb-subset-cff1.cc                              |  53 ++++-----
+ .../fonts/SourceHanSans-Regular.41,3041,4C2E.otf   | Bin 3892 ->
+ 2576 bytes
+ .../SourceHanSans-Regular.41,4C2E.nohints.otf      | Bin 0 -> 2380 bytes
+ ...urceHanSans-Regular.41,4C2E.nosubrs.nohints.otf | Bin 0 -> 2360 bytes
+ .../SourceHanSans-Regular.41,4C2E.nosubrs.otf      | Bin 0 -> 2548 bytes
+ test/api/fonts/SourceHanSans-Regular.41,4C2E.otf   | Bin 2548 ->
+ 2576 bytes
+ test/api/fonts/SourceSansPro-Regular.abc.otf       | Bin 3412 ->
+ 1812 bytes
+ .../api/fonts/SourceSansPro-Regular.ac.nohints.otf | Bin 3228 ->
+ 1592 bytes
+ .../SourceSansPro-Regular.ac.nosubrs.nohints.otf   | Bin 0 -> 1540 bytes
+ .../api/fonts/SourceSansPro-Regular.ac.nosubrs.otf | Bin 0 -> 1632 bytes
+ test/api/fonts/SourceSansPro-Regular.ac.otf        | Bin 3332 ->
+ 1708 bytes
+ test/api/test-subset-cff1.c                        | 122
+ +++++++++++++++++++++
+ 15 files changed, 232 insertions(+), 106 deletions(-)
+
+commit 2c68f34bddbe506d0b22948562f2f59b9a5b6050
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Fri Nov 2 23:06:00 2018 +0200
+
+    [os2] Capitalize table tag and struct
+
+    Other tables follow the case of the OT tag, except this one.
+
+ src/hb-ot-hmtx-table.hh |  6 +++---
+ src/hb-ot-os2-table.hh  | 12 ++++++------
+ src/hb-subset.cc        |  4 ++--
+ 3 files changed, 11 insertions(+), 11 deletions(-)
+
+commit 8034d1dda091998d356e77f249d3c9f50501cc77
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 14:47:42 2018 -0400
+
+    [kern] Implement Format1
+
+    Also, implement backwards kerning for Format1 in kern and kerx.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1350
+
+ src/hb-aat-layout-kerx-table.hh |  11 +++-
+ src/hb-ot-kern-table.hh         | 127
+ ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 136 insertions(+), 2 deletions(-)
+
+commit 46b3885c1a8ea3b85efbdd1704edcee385797c5d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 14:43:38 2018 -0400
+
+    [kern] Set subtable on sanitizer
+
+ src/hb-ot-kern-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 74c7a2c6c892446dcec574986e128967bd570e47
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 14:26:04 2018 -0400
+
+    [kern] Respect more flags
+
+ src/hb-ot-kern-table.hh | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+commit 9f880bad0d7291eaab10d814567c7a680e139c48
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 13:57:41 2018 -0400
+
+    [kern] Minor
+
+    We like check_struct() more.
+
+ src/hb-ot-kern-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 04b82b181d06c229a98314c1620d3ae8a2825267
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 13:47:33 2018 -0400
+
+    Remove pointer cast operators from ArrayOf<>
+
+    ArrayOf<>, unlike UnsizedArrayOf<>, has data before the array.
+    This was confusing.  Remove.
+
+ src/hb-open-type.hh | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit f1df441bedaf5b2c7fadf9954ea39616af87702a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 13:26:15 2018 -0400
+
+    [kern] Comment
+
+ src/hb-ot-kern-table.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 095f5add0b1ca39dd09842594b80fae92f0796e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 13:23:54 2018 -0400
+
+    [kern] Push apply loop to each subtable
+
+ src/hb-ot-kern-table.hh | 153
+ ++++++++++++++++++++++++++++++++++++++----------
+ src/hb-ot-layout.cc     |  28 ++++++---
+ src/hb-ot-layout.hh     |   8 ++-
+ src/hb-ot-shape.cc      |   2 +-
+ 4 files changed, 149 insertions(+), 42 deletions(-)
+
+commit 949dad89a81ff5b6ef92e8737962b667249a3f2b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 12:47:55 2018 -0400
+
+    [kern] Remove accelerator
+
+    It wasn't doing anything.
+
+ src/hb-ot-face.hh       |  2 +-
+ src/hb-ot-kern-table.hh | 55
+ ++++++++++++++-----------------------------------
+ src/hb-ot-layout.cc     |  4 ++--
+ 3 files changed, 18 insertions(+), 43 deletions(-)
+
+commit 0382b7184addf5b3723db40a57790e5e62ac1703
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 12:23:26 2018 -0400
+
+    Use as_array in more places
+
+ src/hb-aat-layout-morx-table.hh |  4 ++--
+ src/hb-ot-layout-gsubgpos.hh    | 22 +++++++++++++---------
+ 2 files changed, 15 insertions(+), 11 deletions(-)
+
+commit 91de9dfcf3bba7cbeef1e709679c8e24ab684c97
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 12:14:21 2018 -0400
+
+    Fix &array_of<>
+
+ src/hb-dsalgs.hh    | 3 +++
+ src/hb-open-type.hh | 4 ++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+commit 9b7cb137946013592c9a5a9f0a3464fb4613577b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 12:00:55 2018 -0400
+
+    Fixup
+
+ src/hb-dsalgs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6e06fe162ed79bb47f62aae03669cd72b99014a0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 11:56:55 2018 -0400
+
+    [kern] Implement Format3
+
+    Untested.
+
+ src/hb-ot-kern-table.hh | 51
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+
+commit c6ef5dbd5c40cc8934756456221e080012a82530
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 11:51:21 2018 -0400
+
+    Add cast operators to hb_array_t
+
+ src/hb-dsalgs.hh | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+commit 72462eb76584a2892f1d961c90fd289240ea9380
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 11:46:24 2018 -0400
+
+    Add UnsizedArrayOf::as_array() instead of hb_array() template
+
+ src/hb-aat-layout-trak-table.hh |  2 +-
+ src/hb-dsalgs.hh                |  2 --
+ src/hb-open-file.hh             |  2 +-
+ src/hb-open-type.hh             | 11 +++--------
+ src/hb-ot-color-cpal-table.hh   |  6 +++---
+ 5 files changed, 8 insertions(+), 15 deletions(-)
+
+commit 1cf075ecb674cc0c7043bffe2fef5ef187c15335
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 11:38:00 2018 -0400
+
+    Add get_size to UnsizedArrayOf
+
+ src/hb-open-type.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit a4a7a623893fd4c8db3a987d81a1c80243006f1e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Nov 2 11:16:43 2018 -0400
+
+    [kern] Add buffer message
+
+ src/hb-ot-kern-table.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 0b2870085ddecdde8370eebc7c2bb346b1992b93
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 22:43:17 2018 -0700
+
+    removed unused code
+
+ src/hb-cff-interp-common.hh | 18 ------------------
+ 1 file changed, 18 deletions(-)
+
+commit 6186dbf1be4da88d9c4f1ef5cea19fd7779f29ab
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 17:25:23 2018 -0700
+
+    added hb_subset_input_set_desubroutinize API
+
+    hooked up with CFF1 subroutinizer
+    a renaming
+
+ src/hb-subset-cff-common.hh |  2 +-
+ src/hb-subset-cff1.cc       |  4 ++--
+ src/hb-subset-input.cc      | 13 +++++++++++++
+ src/hb-subset.h             |  5 +++++
+ util/hb-subset.cc           |  1 +
+ util/options.cc             |  2 +-
+ 6 files changed, 23 insertions(+), 4 deletions(-)
+
+commit b1d0c589154d080ff519c3e80aea923185787b13
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 16:33:46 2018 -0700
+
+    removed extraneous ;s
+
+ src/hb-cff-interp-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 2840a104c1288af79cbda720afa9e37aec6fb29d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 16:18:13 2018 -0700
+
+    tweaks to build with new merge
+
+ src/hb-cff2-interp-cs.hh    | 11 +++++++----
+ src/hb-ot-cff2-table.cc     |  9 +++++----
+ src/hb-ot-cff2-table.hh     |  7 +++----
+ src/hb-subset-cff-common.cc | 12 ++++--------
+ src/hb-subset-cff-common.hh |  3 +--
+ src/hb-subset-cff1.cc       |  3 +--
+ src/hb-subset-cff2.cc       |  3 +--
+ 7 files changed, 22 insertions(+), 26 deletions(-)
+
+commit e600e5440b3b77294df47fae947758137ea02501
+Merge: 82248b92 de96e5c8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 16:13:56 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit de96e5c81c7f473520df93052ecea162baa5a350
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 1 18:13:58 2018 -0400
+
+    [Crap] Avoid operator=
+
+ src/hb-null.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f9353bd68c112dea8962dd586bf5e664f75a2a07
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 1 18:05:22 2018 -0400
+
+    [aat] Rely on vector auto initialization
+
+ src/hb-aat-map.hh | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+commit 5a18d97b35d05c826c242e6847764c2418831a55
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 1 18:01:26 2018 -0400
+
+    [aat] Remove unused forward declaration
+
+ src/hb-aat-map.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 82248b9287e7b208c304e761393b745604a51c6e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 10:36:50 2018 -0700
+
+    fix leak attempt ^2
+
+ src/hb-subset-cff2.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a9c305c2b00b7e793dc3d8333eee43d677aebd42
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 10:31:21 2018 -0700
+
+    fix leaks
+
+ src/hb-subset-cff1.cc | 4 ++--
+ src/hb-subset-cff2.cc | 3 +--
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+commit 049ce078e51bebce50b17889f3edae3db3ea39f5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Nov 1 08:46:21 2018 -0700
+
+    fix bogus width with --no-hinting
+
+ src/hb-cff1-interp-cs.hh | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+commit 07ec792212063851ee41eae33792d3d90d31e6a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Nov 1 10:31:12 2018 -0400
+
+    Warning fix
+
+ src/test-ot-color.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c32280b30fb3844addda31a0d97ae7cb55ef07d2
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 15:31:14 2018 +0330
+
+    [ot-layout] minor
+
+ src/hb-ot-layout.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit cad90be4ea56a85ddc084f86f36dd7129850f6d7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Nov 1 13:39:06 2018 +0330
+
+    [test] minor
+
+ test/api/test-ot-color.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit d56e338a903a5a7c4f8ccd0f4d983cd492243ed6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 31 22:30:34 2018 -0700
+
+    CFF1 no-desubroutinize + no-hinting
+
+    no-desubroutinize option is disabled for now
+    code cleanup (esp. CFF1 width handling)
+    bug fixes & renaming
+
+ src/hb-cff-interp-common.hh      |  49 +++
+ src/hb-cff-interp-cs-common.hh   |  93 +++++-
+ src/hb-cff-interp-dict-common.hh |  45 +--
+ src/hb-cff1-interp-cs.hh         |  66 +++-
+ src/hb-cff2-interp-cs.hh         |   1 +
+ src/hb-ot-cff-common.hh          |  85 ++---
+ src/hb-ot-cff1-table.hh          |  20 +-
+ src/hb-ot-cff2-table.hh          |  25 +-
+ src/hb-subset-cff-common.hh      | 702
+ ++++++++++++++++++++++++++++++++++++---
+ src/hb-subset-cff1.cc            | 242 +++++++++++---
+ src/hb-subset-cff2.cc            |  45 +--
+ src/hb-subset-input.hh           |   1 +
+ src/hb-subset-plan.cc            |   1 +
+ src/hb-subset-plan.hh            |   1 +
+ util/options.cc                  |   2 +
+ util/options.hh                  |   2 +
+ 16 files changed, 1130 insertions(+), 250 deletions(-)
+
+commit 52a00cd87f63c8ab32413a1a9ce792a3e2ec84e2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 19:05:53 2018 -0700
+
+    [aat] Implement 'aalt' mapping
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1160
+
+ src/hb-aat-map.cc | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit 6e3ea269fa1fe0a3de7a8a13c6e853c91231808e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 19:00:11 2018 -0700
+
+    [aat] Add 'afrc' feature mapping
+
+    https://github.com/harfbuzz/harfbuzz/issues/1342#issuecomment-434829028
+
+ src/hb-aat-layout.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 40b19fd46951e2f9b402e59e1fbbf06fde7ecd61
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 18:51:45 2018 -0700
+
+    [aat] Fallback to old style "Letter Case" small caps
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1342
+
+ src/hb-aat-layout-morx-table.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit f9289319481a1e9762ad366b287e781c44ba9fc6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 18:25:05 2018 -0700
+
+    [test] Minor
+
+ test/shaping/run-tests.py | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit cf203af8a33591c163b63dbdf0fd341bc4606190
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 18:21:48 2018 -0700
+
+    Implement space fallback in vertical direction
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1343
+
+ src/hb-ot-shape-fallback.cc                   | 36
+ +++++++++++++++++++--------
+ test/shaping/data/in-house/tests/spaces.tests | 17 +++++++++++++
+ 2 files changed, 42 insertions(+), 11 deletions(-)
+
+commit e01250230b1ad85e49cc0021365d1ee43feb9855
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 18:14:00 2018 -0700
+
+    [hmtx/vmtx] Fix a crasher
+
+ src/hb-ot-hmtx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 36e90ef56e6c0643ef61e947d7361c6fa4eadf10
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 15:09:09 2018 -0700
+
+    [mort] Massage some more
+
+ src/hb-aat-layout-common.hh     | 28 ++++++++++++++++++++++++++++
+ src/hb-aat-layout-morx-table.hh | 21 +++++----------------
+ 2 files changed, 33 insertions(+), 16 deletions(-)
+
+commit cbaff4ef1910e2872bfff61f3d5427c076b3673d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 15:06:12 2018 -0700
+
+    [mort] Some more
+
+ src/hb-aat-layout-morx-table.hh | 34 ++++++++++++++++------------------
+ 1 file changed, 16 insertions(+), 18 deletions(-)
+
+commit 3087046d3144afb50bcc13e4afa2d20d9f71f2c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 14:59:14 2018 -0700
+
+    [mort] Refactor offset-to-index mapping
+
+ src/hb-aat-layout-morx-table.hh | 27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+commit b9db610add702da0a257db2eb21f3a7fb56682f7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 14:22:31 2018 -0700
+
+    Minor
+
+ src/hb-font.cc | 28 ++++++++++++++--------------
+ src/hb-font.h  |  2 +-
+ 2 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 995bf6c6f82d6b2dabcb81e1426910ee82b91b44
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 13:21:33 2018 -0700
+
+    [sbix] Rely on blob->as<> checking size against Type::min_size
+
+ src/hb-ot-color-sbix-table.hh | 6 ------
+ 1 file changed, 6 deletions(-)
+
+commit 4d4e526b5cc703111eb445b7e319a4cd1917489f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 13:19:42 2018 -0700
+
+    Improve blob->as<>
+
+    It's true that blob->as<> should only be called on null or sanitized
+    data.  But this change is safe, so keep it.
+
+ src/hb-blob.hh          | 2 +-
+ src/hb-ot-glyf-table.hh | 3 ++-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit 5854d3fa251069f8158b97a831d1439c2ff8b510
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 10:42:49 2018 -0700
+
+    [set] Warning fix with gcc 8.1
+
+    https://github.com/harfbuzz/harfbuzz/pull/1334
+
+ src/hb-dsalgs.hh | 6 ++++--
+ src/hb-set.hh    | 4 ++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+commit 850a7af3a419c6c4ab92bff59991758a2951d41f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 31 14:20:23 2018 +0330
+
+    [ot-color-test] Remove the non-working exact strike size storing
+    (#1339)
+
+ src/test-ot-color.cc | 135
+ +++++++++++++++++++++++----------------------------
+ 1 file changed, 62 insertions(+), 73 deletions(-)
+
+commit 2e639c47c9d35ff7dc4dde21f744f9ee695a27f3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 31 14:20:14 2018 +0330
+
+    [aat] Fix older compilers by not referencing enum directly (#1340)
+
+ src/hb-aat-layout-morx-table.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 642c9dcf1b34b51ffdbf88ccbef4762aa12a5cbe
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 31 14:02:37 2018 +0330
+
+    [aat] Minor, remove extra semicolons
+
+ src/hb-aat-layout-morx-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit c962d5e714a6f88c4cb20bed219177b1bc4a2dfd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 01:16:33 2018 -0700
+
+    [mort] Make ligatures work
+
+     ./hb-shape Apple_Chancery_10_12.ttf  "Th th ll te to tr fr fu fj"
+    [T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1331
+
+ src/hb-aat-layout-morx-table.hh | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+commit c07798960004439fcd8fa0f4ae33e225428d1065
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 00:36:03 2018 -0700
+
+    [mort] More Ligature work
+
+ src/hb-aat-layout-morx-table.hh | 54
+ ++++++++++++++++++++++++++++++-----------
+ 1 file changed, 40 insertions(+), 14 deletions(-)
+
+commit 431c6e496be56e441ee4b9b705f40a1246bdd0d6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 31 00:15:00 2018 -0700
+
+    [mort] Some Ligature work
+
+ src/hb-aat-layout-morx-table.hh | 38
+ +++++++++++++++++++++++++++++++-------
+ 1 file changed, 31 insertions(+), 7 deletions(-)
+
+commit 28b68cffe4e5ebf82217ebf439f428431d672af3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 23:33:30 2018 -0700
+
+    [mort] Implement / adjust Contextual substitution
+
+ src/hb-aat-layout-morx-table.hh | 70
+ ++++++++++++++++++++++++++++++-----------
+ src/hb-open-type.hh             |  7 +++++
+ 2 files changed, 59 insertions(+), 18 deletions(-)
+
+commit 11dbf0f12926b80d0c308c70a218342280045c23
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 21:49:59 2018 -0700
+
+    [mort] More fixes]
+
+ src/hb-aat-layout-common.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit e1552af95b6c17571f7ee58ebac92f48d93c8f98
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 21:09:05 2018 -0700
+
+    [maxp] Minor
+
+ src/hb-ot-maxp-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0cf282a32e5b0fe1fec454ff293ffe04b33f1112
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 20:51:44 2018 -0700
+
+    [mort] Grind some more
+
+ src/hb-aat-layout-common.hh | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+commit 90667b31bc3e61e68e27966e4781aba456c6b93b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 20:15:28 2018 -0700
+
+    [mort] Hook up more
+
+ src/hb-aat-layout.cc | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+commit 9346b1f158dfd7d25ed0057b40aaa6980a85ea17
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 20:04:13 2018 -0700
+
+    [morx] Remove stale comment
+
+ src/hb-aat-layout-morx-table.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit f864ef215e1354a1e5a3c8796afafba761404e08
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:42:21 2018 -0700
+
+    [mort] More massaging towards mort
+
+ src/hb-aat-layout-morx-table.hh | 53
+ +++++++++++++++++++++--------------------
+ 1 file changed, 27 insertions(+), 26 deletions(-)
+
+commit 2d9467340b1498ccc0cd47bf915b84ab12dfa025
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:33:31 2018 -0700
+
+    [mort] Fix version check in sanitize
+
+ src/hb-aat-layout-morx-table.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit c2527a1bc2b493473f06ea6ae79f0a87b722c4d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:26:16 2018 -0700
+
+    [mort] Make it compile / hook it up
+
+    Untested.
+
+ src/hb-aat-layout-common.hh     | 11 +++++-----
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ src/hb-aat-layout.cc            | 47
+ ++++++++++++++++++++++++++---------------
+ 3 files changed, 36 insertions(+), 24 deletions(-)
+
+commit 933babdc075c27fbcc1b726c3c9b2aa67338c6ad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:22:43 2018 -0700
+
+    [mort] Fixup on previous commit
+
+ src/hb-aat-layout-morx-table.hh | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+commit b053cabacd99ff69144a1459fe02ffd574c2416c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 30 18:41:34 2018 +0330
+
+    [mort] Bring back mort generalizations
+
+    Started by reverting
+    https://github.com/harfbuzz/harfbuzz/commit/1f1c85a5
+
+    Just a starting point, if we agree even mort can come back.
+
+ src/hb-aat-layout-common.hh     |  76 +++++++++++++++++++----
+ src/hb-aat-layout-kerx-table.hh |  17 ++---
+ src/hb-aat-layout-morx-table.hh | 133
+ ++++++++++++++++++++++++----------------
+ src/hb-aat-layout.cc            |  16 ++++-
+ src/hb-ot-face.hh               |   1 +
+ 5 files changed, 171 insertions(+), 72 deletions(-)
+
+commit 5cd544a621f10b307bb97aea27ea54e55aacb2e9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:16:00 2018 -0700
+
+    Fix build
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1338
+
+ src/test-ot-color.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 69297bb21640677532b7030332f803c0768c6579
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 19:06:21 2018 -0700
+
+    [fuzzing] Call hb-ot-color API
+
+ test/fuzzing/hb-shape-fuzzer.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 1019391046cf01524c4ef20c9256a47b7411610b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 15:52:26 2018 -0700
+
+    2.1.0
+
+ NEWS                   | 81
+ ++++++++++++++++++++++++++++++++++++++++++++++++++
+ RELEASING.md           |  3 +-
+ configure.ac           |  2 +-
+ docs/harfbuzz-docs.xml |  1 +
+ src/hb-ot-color.cc     | 22 +++++++++-----
+ src/hb-ot-color.h      |  4 +--
+ src/hb-version.h       |  6 ++--
+ 7 files changed, 105 insertions(+), 14 deletions(-)
+
+commit bfd549daaa078e7edba5a65971b1d3e872664f2d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 14:47:27 2018 -0700
+
+    Fix everything-bot
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0e1ad5a075c6858ca60bad0e2da58b5256e15815
+Author: Garret Rieger <grieger@google.com>
+Date:   Tue Oct 30 11:29:58 2018 -0700
+
+    [subset] Limit the number of scripts and langsys' that should be
+    checked when collecting features.
+
+ src/hb-ot-layout-common.hh |  8 ++++++++
+ src/hb-ot-layout.cc        | 11 ++++++++++-
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+commit a7aba99baab2d6e6105675ceedbe22222fa0f166
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 14:04:09 2018 -0700
+
+    [name] Rename hb_name_id_t to hb_ot_name_id_t
+
+    https://github.com/harfbuzz/harfbuzz/pull/1254
+
+ docs/harfbuzz-sections.txt    |  3 +-
+ src/hb-ot-color-cpal-table.hh | 12 +++---
+ src/hb-ot-color.cc            |  6 +--
+ src/hb-ot-color.h             |  4 +-
+ src/hb-ot-layout.cc           | 44 +++++++++----------
+ src/hb-ot-layout.h            | 28 ++++++-------
+ src/hb-ot-name-table.hh       |  6 +--
+ src/hb-ot-name.cc             | 38 ++++++++---------
+ src/hb-ot-name.h              | 98
+ +++++++++++++++++++++----------------------
+ test/api/test-ot-color.c      | 30 ++++++-------
+ test/api/test-ot-name.c       |  8 ++--
+ 11 files changed, 139 insertions(+), 138 deletions(-)
+
+commit 881e1054bc66fd07489d661dd5c3f84a5d077edc
+Author: Simon Tooke <stooke@redhat.com>
+Date:   Tue Oct 30 14:16:23 2018 -0400
+
+    fix various GCC function pointer warnings
+
+ src/hb-debug.hh | 6 +++---
+ src/hb-set.hh   | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit dc9bd29feac6675c79343b88a06f03f356f9175b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 13:16:07 2018 -0700
+
+    [CBDT] Implement Format18 get_extens
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1327
+
+ src/hb-ot-color-cbdt-table.hh | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+commit a2a7422aaf47dd43c2c55ad48dd15513f9d5b081
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 13:14:56 2018 -0700
+
+    [CBDT] Bound checks in reference_png
+
+ src/hb-ot-color-cbdt-table.hh | 57
+ ++++++++++++++++++++++++++-----------------
+ 1 file changed, 34 insertions(+), 23 deletions(-)
+
+commit f236f790884d7b5c7afb73768724c360d4ea5212
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Tue Oct 30 11:24:56 2018 -0500
+
+    Docs Makefile: sync SGML list to harfbuzz-docs.xml include
+    list. Hopefully fixes distcheck failure.
+
+ docs/Makefile.am | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+commit 9f4b375e396fe65b30c792b9524a732da0b477d1
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Mon Oct 29 17:10:53 2018 -0500
+
+    Usermanual: minor wording updates, build fixes.
+
+ ...rmanual-buffers-language-script-and-direction.xml |  8 +++++++-
+ docs/usermanual-clusters.xml                         |  6 ++++++
+ docs/usermanual-fonts-and-faces.xml                  |  8 +++++++-
+ docs/usermanual-getting-started.xml                  |  6 ++++++
+ docs/usermanual-glyph-information.xml                |  8 +++++++-
+ docs/usermanual-install-harfbuzz.xml                 | 20
+ +++++++++++++++++---
+ docs/usermanual-opentype-features.xml                |  8 +++++++-
+ docs/usermanual-shaping-concepts.xml                 |  6 ++++++
+ docs/usermanual-what-is-harfbuzz.xml                 | 12 +++++++-----
+ 9 files changed, 70 insertions(+), 12 deletions(-)
+
+commit e110032b914db9f417cc152b2beb51cda0a91dd7
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Mon Oct 29 16:42:59 2018 -0500
+
+    Usermanual: update DTD in chapter XML to avoid HTML entity parsing
+    errors.
+
+ docs/usermanual-what-is-harfbuzz.xml | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+commit 01400f7425f7aec852f39ebee17aa502a74025fb
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Sat Oct 20 17:21:49 2018 +0100
+
+    Usermanual; minor wording changes.
+
+ docs/usermanual-getting-started.xml  | 14 +++++++-------
+ docs/usermanual-install-harfbuzz.xml | 10 +++++++++-
+ docs/usermanual-what-is-harfbuzz.xml | 31 ++++++++++---------------------
+ 3 files changed, 26 insertions(+), 29 deletions(-)
+
+commit e89f43dc0884cb4a73beff86e49b7bd8565a01f1
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 16:12:45 2018 +0100
+
+    Minor; rewording unsafe-to-break note.
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/usermanual-getting-started.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ccdfb634382596a6114380c72f2f344b1af23f94
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 15:46:04 2018 +0100
+
+    Trivial; typo.
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/usermanual-what-is-harfbuzz.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 722099487be72346e7109872b6abf30696f3b7c3
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 15:45:24 2018 +0100
+
+    Minor; simplify example code
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/usermanual-getting-started.xml | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 6e4dd58a4af003eeec93cbe90d1258d91a38b53c
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 15:44:51 2018 +0100
+
+    Minor: simplify example code
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/usermanual-getting-started.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f9ee0deceebd8952a8d80f3fd7b264b33e70f703
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 15:41:00 2018 +0100
+
+    Minor; drop 'OpenType' from sentence
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/usermanual-what-is-harfbuzz.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f028da59d902c39e61021b48fc73f2821a9f3be2
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Sat Oct 20 15:18:29 2018 +0100
+
+    Minor.
+
+ docs/harfbuzz-docs.xml | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+commit ed5547f828fe7559cc3331f05780ae9f041b1e0f
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 15:00:52 2018 +0100
+
+    Use 'glyphs' instead of 'text'
+
+    Co-Authored-By: n8willis <nwillis@glyphography.com>
+
+ docs/harfbuzz-docs.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 236285545b5da8513f2b61fc8066ba78308a555a
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Wed Oct 17 10:10:48 2018 -0500
+
+    Docs: minor, update Makefile w new file name.
+
+ docs/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 163ab81ab0f4000d968cc55b418402497e605e6c
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Tue Oct 16 17:48:15 2018 -0500
+
+    Docs: rename Hello HarfBuzz to Getting Started.
+
+ docs/harfbuzz-docs.xml                                                 |
+ 2 +-
+ docs/{usermanual-hello-harfbuzz.xml => usermanual-getting-started.xml}
+ | 0
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 9e7efa3f47557a77852a15d89619787fd9933ed1
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Tue Oct 16 17:46:03 2018 -0500
+
+    Docs: usermanual, add API Overview to Hello HarfBuzz chapter. Start
+    Terminology section.
+
+ docs/usermanual-hello-harfbuzz.xml | 309
+ +++++++++++++++++++++++++------------
+ 1 file changed, 212 insertions(+), 97 deletions(-)
+
+commit 3a27e8fb97f716c17b03e3a4a634a4900bcb6045
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Fri Oct 12 18:23:26 2018 -0500
+
+    Docs: usermanual, add Shaping Concepts chapter.
+
+ docs/harfbuzz-docs.xml               |   5 +-
+ docs/usermanual-shaping-concepts.xml | 368
+ +++++++++++++++++++++++++++++++++++
+ 2 files changed, 371 insertions(+), 2 deletions(-)
+
+commit 9aa865dcc68ec207741e07ba3f7aacf4ac750c1c
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Fri Oct 12 18:22:41 2018 -0500
+
+    Docs: usermanual, minor cleanup to What Is HarfBuzz chapter.
+
+ docs/usermanual-what-is-harfbuzz.xml | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 443f87213272be5ae0579dce4749b2036dfe3815
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Thu Oct 11 15:40:08 2018 -0500
+
+    Docs: move harfbuzz-ng-vs-old discussion down below the TOC; put
+    in note.
+
+ docs/harfbuzz-docs.xml | 63
+ ++++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 43 insertions(+), 20 deletions(-)
+
+commit 792af5d254fddcdc4292dffb76b81d65754e65a9
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Thu Oct 11 14:05:59 2018 -0500
+
+    Docs: flesh out config options in Usermanual:Install chapter.
+
+ docs/usermanual-install-harfbuzz.xml | 108
+ +++++++++++++++++++++++++++--------
+ 1 file changed, 85 insertions(+), 23 deletions(-)
+
+commit 325e2745cfa55f9ef114ee8eeaf7bd8176743822
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Wed Oct 10 17:01:21 2018 -0500
+
+    Docs: add basic config-options section to Usermanual Installation
+    chapter.
+
+ docs/usermanual-install-harfbuzz.xml | 132
+ ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 131 insertions(+), 1 deletion(-)
+
+commit 97c1c46cd2241d77b531a582dd1a2432af976357
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Wed Oct 10 16:38:22 2018 -0500
+
+    Docs: update and linearize build instructions; add installation
+    overview material.
+
+ docs/usermanual-install-harfbuzz.xml | 229
+ ++++++++++++++++++++++++++++-------
+ 1 file changed, 188 insertions(+), 41 deletions(-)
+
+commit 088755f9e654d2ec638dce0c68d523084b9eaf5a
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Wed Oct 10 16:37:29 2018 -0500
+
+    Docs: update usermanual What Is HarfBuzz material.
+
+ docs/usermanual-what-is-harfbuzz.xml | 220
+ +++++++++++++++++++++++++++--------
+ 1 file changed, 172 insertions(+), 48 deletions(-)
+
+commit 0956ab41851d30f50c39c28730cf30ea0bbc5466
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Fri Sep 28 17:15:59 2018 -0500
+
+    Docs: Move What-HarfBuzz-doesnt-do to Usermanual-what-is-HarfBuzz.
+
+ docs/usermanual-hello-harfbuzz.xml   |  98
+ +++------------------------------
+ docs/usermanual-what-is-harfbuzz.xml | 101
+ +++++++++++++++++++++++++++++++++--
+ 2 files changed, 104 insertions(+), 95 deletions(-)
+
+commit fd270beedb331c4685e918f5a3ef5789a23ffaeb
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Fri Sep 28 16:36:38 2018 -0500
+
+    Docs: Usermanual- What is HarfBuzz; add intro to shaping concepts.
+
+ docs/usermanual-what-is-harfbuzz.xml | 51
+ ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+
+commit d9fd92721002726c4aeaae9cc3a519a41f694e48
+Author: Nathan Willis <nwillis@glyphography.com>
+Date:   Fri Sep 28 16:07:37 2018 -0500
+
+    Docs: update Usermanual-What Is HarfBuzz.
+
+ docs/usermanual-what-is-harfbuzz.xml | 199
+ +++++++++++++++++++++++------------
+ 1 file changed, 130 insertions(+), 69 deletions(-)
+
+commit 0af3d176a64c0a57c7acb2a64ce8b9d08f449241
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Tue Oct 30 17:05:28 2018 +0200
+
+    [sbix] Fix memory leak in early return
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11210
+
+ src/hb-ot-color-sbix-table.hh                             |   3 +++
+ ...zz-testcase-minimized-hb-shape-fuzzer-5768601332613120 | Bin 0 ->
+ 108 bytes
+ 2 files changed, 3 insertions(+)
+
+commit edaa768253cfeb97d614537253f90d47aa93ff6f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 01:35:58 2018 -0700
+
+    [util] Use fgets instead of getline such that windows passes
+
+ util/hb-shape.cc | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 56738429d667f6c35e5c7af30b51604fc133c23c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 01:33:22 2018 -0700
+
+    [test] Fix warnings
+
+ test/api/test-ot-tag.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 138f9e0f25752bbf7f8e867f230ca91442f40028
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 01:31:13 2018 -0700
+
+    Minor
+
+ src/hb-machinery.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 83a612739accf6b0f2e1cb1be15097402f7ecf33
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 01:24:23 2018 -0700
+
+    [util] Minor
+
+ util/options.cc | 6 ------
+ util/options.hh | 8 ++------
+ 2 files changed, 2 insertions(+), 12 deletions(-)
+
+commit 64e41d2c89c533f554e49ffbd18e6653a70ab999
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 01:08:34 2018 -0700
+
+    [test] Fix Python3
+
+ test/shaping/run-tests.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f7a08cd41df1ff3e44aa838306218ae0565b7273
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 30 11:29:09 2018 +0330
+
+    Fix extra semicolon issues and test that on CI (#1330)
+
+ .circleci/config.yml         |  2 +-
+ src/hb-machinery.hh          | 16 ++++++++--------
+ src/hb-ot-layout-common.hh   |  6 +++---
+ src/hb-ot-layout-gsubgpos.hh |  2 +-
+ src/hb.hh                    |  2 +-
+ util/options.hh              |  2 +-
+ 6 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 422debb830fe150c26e1628f77531f41f0871325
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 00:51:43 2018 -0700
+
+    [test/shaping] Spawn one hb-shape per test file
+
+    Speeds up runnings in-house tests from over 20s to 2s.
+
+ test/shaping/run-tests.py | 32 ++++++++++++--------------------
+ 1 file changed, 12 insertions(+), 20 deletions(-)
+
+commit 58e20f53bf61244e3eef09be8ebed60aaf52fb11
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 00:50:18 2018 -0700
+
+    [util] Add hb-shape --batch
+
+ util/hb-shape.cc | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+commit 6131fb6283cff87333db14b9b32e92be6139c3d6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 30 00:38:01 2018 -0700
+
+    [util] Don't close stdin/stdout
+
+ util/options.cc | 6 ++++++
+ util/options.hh | 8 ++++++--
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+commit 7e998d193a1429b42bb69582f9e5738aa6fd1a72
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 23:31:42 2018 -0700
+
+    Fix spurious warning re uninitialized use
+
+ src/hb-ot-layout-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 1b7bfb5e1864fc355715b536faac6693b5ce0218
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 30 10:19:40 2018 +0330
+
+    [cmake] Make build of tests and subset optional (#1329)
+
+ .circleci/config.yml |  2 +-
+ CMakeLists.txt       | 19 ++++++-------------
+ 2 files changed, 7 insertions(+), 14 deletions(-)
+
+commit b186274362725b7501211c2a782c1a0badd57107
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 23:21:14 2018 -0700
+
+    [set/map] Fix uninitialized memory
+
+    I keep forgetting that primitive types are NOT initialized during
+    construction. :|
+
+ src/hb-map.hh    | 4 ++--
+ src/hb-object.hh | 1 +
+ src/hb-set.hh    | 4 ++--
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+commit ad3cededdd5ee6a364161e9d27e4cf4d95a80177
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 22:53:16 2018 -0700
+
+    [fuzzing] Make test runners less verbose
+
+ test/fuzzing/run-shape-fuzzer-tests.py  | 3 ++-
+ test/fuzzing/run-subset-fuzzer-tests.py | 1 -
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 4ef671f25f38895e3f87cd69687670c3d8ea4600
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 22:46:19 2018 -0700
+
+    [unicode] Fix a long-standing double-declaration warning
+
+ src/hb-unicode.cc | 31 +++++++------------------------
+ 1 file changed, 7 insertions(+), 24 deletions(-)
+
+commit 166ae8b0aa3b1e7298a1bbb872647cb352a0f924
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 22:40:37 2018 -0700
+
+    Remove now unused hb_auto_t<>
+
+ src/hb-dsalgs.hh | 20 --------------------
+ 1 file changed, 20 deletions(-)
+
+commit 56e0fd345c4e68753123a05cd80291e933d71061
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 22:35:44 2018 -0700
+
+    Remove last use of hb_auto_t<>
+
+ src/hb-ot-cmap-table.hh | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit ca5e5a4979fa4aca873ba986e60b3010aaf0b1de
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 22:30:21 2018 -0700
+
+    Port Coverage::Iter off hb_auto_t<>
+
+ src/hb-ot-layout-common.hh     |  4 +---
+ src/hb-ot-layout-gpos-table.hh |  2 +-
+ src/hb-ot-layout-gsub-table.hh | 26 +++++++++++++-------------
+ src/hb-ot-layout-gsubgpos.hh   |  8 ++++----
+ 4 files changed, 19 insertions(+), 21 deletions(-)
+
+commit 3a4e5dd425a2a37ff4c37db953943386c0b6e5d8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 18:05:25 2018 -0700
+
+    Remove a few unnecessary hb_auto_t<>'s
+
+    See a85641446c30247c4e948263f0f8c1147ed4efb9
+
+ src/hb-coretext.cc             |  8 ++++----
+ src/hb-ot-cmap-table.hh        |  6 ++----
+ src/hb-ot-layout-gsub-table.hh |  8 ++++----
+ src/hb-ot-layout-gsubgpos.hh   |  2 +-
+ src/hb-ot-layout.cc            | 10 +++++-----
+ src/hb-subset-plan.cc          |  2 +-
+ src/hb-subset.cc               |  2 +-
+ src/hb-uniscribe.cc            | 12 ++++++------
+ 8 files changed, 24 insertions(+), 26 deletions(-)
+
+commit 67a22f377dee0dbd89f301f0a1fec6f787867b5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 17:37:41 2018 -0700
+
+    [set/map/vector] Make constructable, but not copy or assignable
+
+    Disable copy/assign on them, as they shouldn't.
+
+    Make constructor / destructor call init_shallow/fini_shallow,
+    and make those idempotent.  So, these three can be constructed
+    on stack now and no init/fini call is needed.  As such,
+    hb_auto_t<> is not needed anymore.  I'll remove that separately.
+
+ src/hb-map.hh    |  6 ++++++
+ src/hb-set.hh    |  5 +++++
+ src/hb-vector.hh | 37 ++++++++++++++++++++-----------------
+ src/hb.hh        | 12 ++++++++++++
+ 4 files changed, 43 insertions(+), 17 deletions(-)
+
+commit ea0e51d1b161245aaf5ad0f844bb5316b1cbcd5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 16:00:23 2018 -0700
+
+    Add HB_NO_CREATE_COPY_ASSIGN
+
+ src/hb-open-type.hh | 10 +++++-----
+ src/hb.hh           | 15 +++++++++------
+ 2 files changed, 14 insertions(+), 11 deletions(-)
+
+commit 5b563640b2df5b100130c9901b666713b2e1767e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 15:58:44 2018 -0700
+
+    Remove HB_DISALLOW_COPY_AND_ASSIGN from hb_ot_shape_planner_t
+
+    It was arbitrary that this struct had it and not dozens of others.
+
+ src/hb-ot-shape.hh | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 14b353c1852be64db244f84bf5e95b4b7f3e65b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 15:29:13 2018 -0700
+
+    One more iteration
+
+ src/hb.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit c7c5df9ffd4f7bcc84a9a02a565ccc1807cca529
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 15:16:52 2018 -0700
+
+    Try fixing older bots
+
+    Older C++ doesn't allow struct-with-constructor in union.
+
+ src/hb.hh | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+commit be87959a67b8ccf2b21d3cfdb7d16202f18df670
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 15:16:38 2018 -0700
+
+    [cmap] Minor
+
+ src/hb-ot-cmap-table.hh | 16 ++--------------
+ 1 file changed, 2 insertions(+), 14 deletions(-)
+
+commit 35d410f2bad62e98f3634c5ee156d0aea9031067
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 14:45:44 2018 -0700
+
+    Remove ASSERT_POD
+
+    Newer compilers / language allows structs with constructor in union.
+    So, this was not actually testing anything.  Indeed, the recent
+    change in DISALLOW_COPY *is* making some of our types non-POD.
+    That broke some bots.
+
+    Just remove this since it wasn't doing much, and I'd rather have
+    DISALLOW_COPY.
+
+ src/hb-blob.hh                             |  1 -
+ src/hb-buffer.hh                           |  1 -
+ src/hb-face.hh                             |  1 -
+ src/hb-font.hh                             |  2 --
+ src/hb-machinery.hh                        |  5 +----
+ src/hb-object.hh                           |  6 +-----
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 --
+ src/hb-ot-shape-complex-arabic.cc          |  2 --
+ src/hb-ot-shape-complex-hangul.cc          |  2 --
+ src/hb-ot-shape-complex-indic.cc           |  2 --
+ src/hb-ot-shape-complex-khmer.cc           |  2 --
+ src/hb-ot-shape-complex-use.cc             |  2 --
+ src/hb-set-digest.hh                       |  4 ----
+ src/hb-shape-plan.hh                       |  1 -
+ src/hb-subset-input.hh                     |  1 -
+ src/hb-subset-plan.hh                      |  1 -
+ src/hb-unicode.hh                          |  1 -
+ src/hb.hh                                  | 26
+ --------------------------
+ 18 files changed, 2 insertions(+), 60 deletions(-)
+
+commit 6f0454e176efdb8b99c8aa59b5ad765ca455b8d6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 13:51:15 2018 -0700
+
+    Fix extra-semicolon warnings
+
+ src/hb-machinery.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit a256a92b3fbb72487cf073a63e646eab952b42ed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 11:25:35 2018 -0700
+
+    Make Array types uncopyable-unassignable
+
+    Finally!  Catches hard-to-find errors like this:
+
+    -    const SortedArrayOf<SVGDocumentIndexEntry> docs =
+    this+svgDocEntries;
+    +    const SortedArrayOf<SVGDocumentIndexEntry> &docs =
+    this+svgDocEntries;
+
+    We implement this for our array types.  This, in turn, trickles down
+    into all types that embed the arrays.  So, as long as we define all
+    open-ended structs in terms of Array types (all can be done using
+    UnsizedArrayOf), this achieves the goal of making uncopyable all
+    structs that are variable-sized.  Yay!
+
+ src/hb-open-type.hh | 11 +++++++++++
+ src/hb.hh           |  6 ++++++
+ 2 files changed, 17 insertions(+)
+
+commit 31cc1f74b7028ef88fa0e93e7f12166c7e06de8e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 11:14:37 2018 -0700
+
+    [svg] Minor
+
+ src/hb-ot-color-svg-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 1366bb9760d0f171f8f655e5739e74dfd2537652
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 29 11:01:25 2018 -0700
+
+    Fix g-i warnings
+
+ src/hb-ot-color.h | 4 +++-
+ src/hb-ot-name.cc | 4 ++--
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+commit ae802c2c6e001492f8f639e4c24546f0e21d86c7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 13:42:14 2018 +0330
+
+    [test-ot-color] Minor
+
+ src/test-ot-color.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7170e35096f0afd084be1350d080695c70c65d40
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 13:11:01 2018 +0330
+
+    Rename deprecated symbols list file name and clean it up (#1328)
+
+ src/Makefile.am      | 6 +++---
+ src/gen-def.py       | 9 ++++-----
+ test/api/Makefile.am | 2 +-
+ 3 files changed, 8 insertions(+), 9 deletions(-)
+
+commit 1dfe964378e97e45eedf9db9b9a7f675fe38c0bf
+Merge: f10252b4 9c692e5b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 12:34:33 2018 +0330
+
+    Merge pull request #1326 from ebraminio/test-ot-color
+
+    Revive and rename dump-emoji to test-ot-color but use public APIs
+    instead
+
+commit 9c692e5b8d195d8e82538594d89865c609d708f3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 11:36:11 2018 +0330
+
+    [test-ot-color] Use public APIs on the tool
+
+ src/Makefile.am      |   9 +++
+ src/test-ot-color.cc | 184
+ +++++++++++++++++++++++++++++----------------------
+ 2 files changed, 113 insertions(+), 80 deletions(-)
+
+commit fb525f8943b43fe241424c93461bee2b94af28e3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 09:43:17 2018 +0330
+
+    Rename dump-emoji to test-ot-color
+
+ src/{dump-emoji.cc => test-ot-color.cc} | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 81bcf47e9ea7eb447ff95ce48ecbc5c4439cb53f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 09:40:39 2018 +0330
+
+    Revive dump-emoji
+
+ src/dump-emoji.cc | 322
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 322 insertions(+)
+
+commit f10252b4b637b4aa0b74bb75963ae1e1a41b5b9f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 10:29:58 2018 +0330
+
+    [svg] Fix incorrect array referencing
+
+ src/hb-ot-color-svg-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5eb251aab041d89b06b0d3f65906ff6712608263
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:16:13 2018 -0700
+
+    [cbdt] Implement strike selection logic
+
+ src/hb-ot-color-cbdt-table.hh | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+commit 98bddbc8ef3330bc5635f6255e6b9c16593a1934
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:14:15 2018 -0700
+
+    [sbix] Minor
+
+ src/hb-ot-color-sbix-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 8cffee0577284839a24d9fb863206886d2373974
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:07:59 2018 -0700
+
+    [cbdt] Simplify more
+
+ src/hb-ot-color-cbdt-table.hh | 22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+commit 574579d3766b7b42e62495cb9a98f3ffd91079e8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:04:37 2018 -0700
+
+    [color] Rename get_strike() to choose_strike()
+
+ src/hb-ot-color-cbdt-table.hh |  8 ++++----
+ src/hb-ot-color-sbix-table.hh | 10 +++++-----
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+commit 0aa90271fdbb2b85389cd5af029b6d4468fb8146
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:03:20 2018 -0700
+
+    [tests] Fix for recent rounding change in CBDT
+
+ test/shaping/data/in-house/tests/color-fonts.tests | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e2ba96da4c39ba5fe941bf2704c1e7cc5f98034f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 23:01:57 2018 -0700
+
+    [cbdt] Refactor get_strike()
+
+ src/hb-ot-color-cbdt-table.hh | 39
+ ++++++++++++++++-----------------------
+ src/hb-ot-color.cc            |  2 +-
+ 2 files changed, 17 insertions(+), 24 deletions(-)
+
+commit 6983cca9c865752fe0a9a065f9b0278b686c3abc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 22:46:18 2018 -0700
+
+    [cbdt] Minor
+
+ src/hb-ot-color-cbdt-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e998fb9fbfbd79b476d758238af60f6a4ddff20c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 22:45:53 2018 -0700
+
+    [color] Round extents when scaling
+
+ src/hb-ot-color-cbdt-table.hh | 12 +++++++-----
+ src/hb-ot-color-sbix-table.hh | 12 ++++++------
+ 2 files changed, 13 insertions(+), 11 deletions(-)
+
+commit c929ccfcea18c5c35d6d41ae921845eeffba978a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 08:41:13 2018 +0330
+
+    [ot-color/png] Consider strike ppem on scaling
+
+ src/hb-ot-color-cbdt-table.hh |  5 +++--
+ src/hb-ot-color-sbix-table.hh | 23 +++++++++++++++++++----
+ src/hb-ot-color.cc            |  2 +-
+ src/hb-ot-font.cc             |  2 +-
+ test/api/test-ot-color.c      |  4 ++--
+ 5 files changed, 26 insertions(+), 10 deletions(-)
+
+commit a8c9facf7a73cca39e3fed1f637db4858e64414a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 18:32:37 2018 -0700
+
+    [svg] Cosmetic
+
+ src/hb-ot-color-svg-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 9c1460e5685448ad4eac8faff9f05e456f87ed28
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 18:29:14 2018 -0700
+
+    [svg] Use SortedArrayOf.bsearch
+
+ src/hb-ot-color-svg-table.hh | 18 +++---------------
+ 1 file changed, 3 insertions(+), 15 deletions(-)
+
+commit 18dd6363a5021cfd770b431a6320386f94447674
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 18:26:49 2018 -0700
+
+    [svg] Minor
+
+ src/hb-ot-color-svg-table.hh | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+commit 4876c938a20af356988d566ba95472d3bcbb133d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 18:01:25 2018 -0700
+
+    [sbix] Comment
+
+ src/hb-ot-color-sbix-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 519fca101466283ca5c993dec2ec2c6891d8add5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 16:32:20 2018 -0700
+
+    [color] Minor
+
+ src/hb-ot-color.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e8ff27c2082ffcf3bd213e7a77d823dc1809857e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 16:29:09 2018 -0700
+
+    Minor
+
+ src/hb-open-type.hh        | 6 ++++--
+ src/hb-ot-layout-common.hh | 4 ++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+commit 65621723815138150e8a6354413ed14d53cf35b5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 16:27:18 2018 -0700
+
+    [sbix] Use LOffsetLArrayOf<>
+
+ src/hb-open-type.hh           | 2 ++
+ src/hb-ot-color-sbix-table.hh | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+commit a3ddd8067f266e49d9451c53a0fd40aff8551af7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 16:26:03 2018 -0700
+
+    [sbix] Add get_strike
+
+ src/hb-ot-color-sbix-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 95524ed9bccdcd0d6a46c5dcc372e96a0c34b5f0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:58:48 2018 -0700
+
+    [sbix] Remove sbix_len
+
+ src/hb-ot-color-sbix-table.hh | 29 +++++++++++++++++++++--------
+ 1 file changed, 21 insertions(+), 8 deletions(-)
+
+commit 69e9846452f829f82f6866a683845167b3d3d6e5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:53:11 2018 -0700
+
+    [sbix] Fix get_glyph_blob() on Null object
+
+ src/hb-ot-color-sbix-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 4e0ee2af091634198c4b9b17036d9391a4e6b084
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:44:40 2018 -0700
+
+    [sbix] Simplify ppem access
+
+    If struct members are simple and needed publicly, we make them public.
+
+ src/hb-ot-color-sbix-table.hh | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+commit 6ac9a4eaa3a47c9b9f2c7aa123255e82ccc53551
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:43:54 2018 -0700
+
+    [sbix] Simplify glyph_length calc
+
+ src/hb-ot-color-sbix-table.hh | 22 +++++-----------------
+ 1 file changed, 5 insertions(+), 17 deletions(-)
+
+commit 0730d623854dc17ce0c3f1f2755a90b656c8e52c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:38:42 2018 -0700
+
+    [sbix] Check glyph data end is in range
+
+ src/hb-ot-color-sbix-table.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit b76dc03108d04975335dbf3580f8d02321cb5d25
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:36:17 2018 -0700
+
+    [sbix] Reduce code
+
+ src/hb-ot-color-sbix-table.hh | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 50fb02a219dbf168d300c4ccf9f29aee38a78e6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:33:12 2018 -0700
+
+    [sbix] Check glyph id before looking into unsafe array
+
+    That 'Z' at end of imageOffsetsZ is a reminder that you should
+    check...
+
+ src/hb-ot-color-sbix-table.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit a8cb9c73da29afa89b0253b6475ff220613e100a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:30:57 2018 -0700
+
+    [sbix] Simplify 'dupe' handling logic
+
+ src/hb-ot-color-sbix-table.hh | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+commit d7eb534e59064633732959c3771b6557cc97005e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:27:04 2018 -0700
+
+    [sbix] Check offsets before proceeding
+
+ src/hb-ot-color-sbix-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit c8380bd3e4a2e51dfbe2e44e19738445be16ac75
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:20:33 2018 -0700
+
+    [color] Remove more dump-emoji cruft
+
+ src/hb-ot-color-cbdt-table.hh | 53
+ -------------------------------------------
+ src/hb-ot-color-sbix-table.hh | 13 -----------
+ 2 files changed, 66 deletions(-)
+
+commit 68f2c832c894d71715073d4748ad321a9d271a0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:18:55 2018 -0700
+
+    Remove dump-emoji
+
+ src/Makefile.am               |   9 --
+ src/dump-emoji.cc             | 322
+ ------------------------------------------
+ src/hb-ot-color-sbix-table.hh |   4 +-
+ 3 files changed, 3 insertions(+), 332 deletions(-)
+
+commit b46de42b3a4bdf110154f4f067656f153f5a7d1b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:13:45 2018 -0700
+
+    [sbix] Fix order of parameters
+
+ src/hb-ot-color-sbix-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a91cda72abdfc5e401510474c59dd14026e8b6cb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:12:05 2018 -0700
+
+    [sbix] Remove redundant parameter
+
+ src/hb-ot-color-sbix-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c712005f55b2a1e5c782302d8a548cf1231c01f0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:11:10 2018 -0700
+
+    [sbix] Add get_strike()
+
+ src/hb-ot-color-sbix-table.hh | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+commit 400bc3f030b4ffebe24aa3562d8eb5fcc1cf4bdd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:05:40 2018 -0700
+
+    [sbix] Remove a couple of extra checks
+
+ src/hb-ot-color-sbix-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 3770282c837aacbf49b16be1986c91a608faa7da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:02:53 2018 -0700
+
+    [sbix] Rename sbix_table to table in accelerator
+
+ src/hb-ot-color-sbix-table.hh | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit 7346841807ad96fc65bfc6ee9e78c3f190488f2a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 15:00:13 2018 -0700
+
+    [cbdt] Rename reference_blob_for_glyph() to reference_png()
+
+ src/hb-ot-color-cbdt-table.hh | 8 ++++----
+ src/hb-ot-color.cc            | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 1f33b8525d578323d6c798c08fc23c56896f9de0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 14:56:55 2018 -0700
+
+    [sbix] Rename ugly reference_blob_for_glyph() to reference_png()
+
+ src/hb-ot-color-sbix-table.hh | 16 +++++++---------
+ src/hb-ot-color.cc            |  4 +---
+ 2 files changed, 8 insertions(+), 12 deletions(-)
+
+commit 946b5344193183133bfc9799e26d3d0436d86404
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 14:52:25 2018 -0700
+
+    [sbix] Fix uninitialized variables
+
+ src/hb-ot-color-sbix-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 01c7d53fb739b547f3633972194893f68a4738bc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 14:51:18 2018 -0700
+
+    [sbix] Select best strike based on ppem
+
+ src/hb-ot-color-sbix-table.hh | 50
+ ++++++++++++++++++++++++-------------------
+ src/hb-ot-color.cc            |  3 +--
+ src/hb-ot-font.cc             |  2 +-
+ 3 files changed, 30 insertions(+), 25 deletions(-)
+
+commit f9f26bff4c79d65a92affd6b73e2b3de017f2d6d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 14:20:50 2018 -0700
+
+    [sbix] Move code around. Add get_extents()
+
+ src/hb-ot-color-sbix-table.hh | 15 +++++++++++++--
+ src/hb-ot-font.cc             |  2 +-
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+commit 48bc3039cb46d2b8cf672d86b63b4235a86252e6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 14:16:52 2018 -0700
+
+    [sbix] Check blob length against PNG header leangth
+
+ src/hb-ot-color-sbix-table.hh | 37 +++++++++++++++++++++++--------------
+ 1 file changed, 23 insertions(+), 14 deletions(-)
+
+commit d3ec31a57cb99048fb33bca65041da9dc884d8cb
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 00:28:44 2018 +0330
+
+    [ot-color] More on PNGHeader fields
+
+ src/hb-ot-color-sbix-table.hh | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+commit 35fa3d326096639a33635e19f204a9cb31f20826
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 00:07:26 2018 +0330
+
+    [ot-color] Apply Behdad comment
+
+ src/hb-ot-color-sbix-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 307d61867a2b70073eecd1e0cb9b7d912e1c3f06
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 29 00:03:01 2018 +0330
+
+    [ot-color] Make PNGHeader reading actually work
+
+ src/hb-ot-color-sbix-table.hh | 6 +++---
+ test/api/test-ot-color.c      | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 632e9af862aba49ab31343c4fd07dffef6d2749f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 28 23:43:50 2018 +0330
+
+    [ot-color] Implement PNGHeader and test it, it doesn't work however
+
+ src/hb-ot-color-sbix-table.hh | 20 +++++++++++++++-----
+ src/hb-ot-font.cc             |  4 +---
+ test/api/test-ot-color.c      | 16 ++++++++++++++++
+ 3 files changed, 32 insertions(+), 8 deletions(-)
+
+commit 38706a0746822865008f810f9f577740c32580fa
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 28 23:19:04 2018 +0330
+
+    [ot-color] Preparation for setting PNG width/height in extents
+
+ src/dump-emoji.cc             |  7 +++---
+ src/hb-ot-color-sbix-table.hh | 52
+ +++++++++++++++++++++++++++++++++++--------
+ src/hb-ot-color.cc            | 14 +++++-------
+ src/hb-ot-font.cc             |  7 +++++-
+ 4 files changed, 59 insertions(+), 21 deletions(-)
+
+commit d6d6f3bc225bab57c1ab29b41876c98ac4ec1e4d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 11:41:33 2018 -0700
+
+    [docs] Add comment
+
+ src/hb-ot-font.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 3d4c1f6a41022ec99adefa2bdd2489622e2f9a66
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 28 21:38:56 2018 +0330
+
+    [ot-color] Apply Behdad reviews
+
+ docs/harfbuzz-sections.txt    |  4 ++--
+ src/hb-ot-color-cbdt-table.hh | 15 ++++-----------
+ src/hb-ot-color-sbix-table.hh |  6 ++----
+ src/hb-ot-color.cc            |  8 ++++----
+ src/hb-ot-color.h             |  4 ++--
+ test/api/test-ot-color.c      | 14 +++++++-------
+ 6 files changed, 21 insertions(+), 30 deletions(-)
+
+commit 8ef0d2ef928ac47278d7c6db8c8040a47f076e85
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 28 20:09:40 2018 +0330
+
+    [ot-color] Apply Behdad comment
+
+ src/dump-emoji.cc             |  2 +-
+ src/hb-ot-color-cbdt-table.hh | 16 +++++++---------
+ src/hb-ot-color-sbix-table.hh | 14 ++++----------
+ src/hb-ot-color.cc            | 22 +++++++---------------
+ src/hb-ot-color.h             |  5 +----
+ test/api/test-ot-color.c      | 15 ++++-----------
+ 6 files changed, 24 insertions(+), 50 deletions(-)
+
+commit dbd419bedef06a07c844b6a748a5e2868016000c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 15:15:24 2018 +0330
+
+    [ot-color] Add public API for CBDT/sbix/SVG color Emojis
+
+ docs/harfbuzz-sections.txt |  4 ++++
+ src/dump-emoji.cc          |  4 ++--
+ src/hb-ot-color.cc         | 39 ++++-----------------------------------
+ src/hb-ot-color.h          | 24 ++++++++++++++++++++++++
+ test/api/test-ot-color.c   |  8 ++------
+ 5 files changed, 36 insertions(+), 43 deletions(-)
+
+commit 6ce49a921a80f1238ddc537f77a1fceea5274a21
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 08:26:30 2018 -0700
+
+    [name] Change hb_name_id_t back to unsigned int
+
+    https://github.com/harfbuzz/harfbuzz/commit/d941f66c75fe26f909b1ba248535cc372bbde851#commitcomment-31076011
+
+ docs/harfbuzz-sections.txt    |  2 --
+ src/hb-ot-color-cpal-table.hh |  4 ++--
+ src/hb-ot-layout.cc           | 12 ++++++------
+ src/hb-ot-name-table.hh       |  2 +-
+ src/hb-ot-name.h              |  6 +++---
+ src/test-size-params.cc       |  2 +-
+ 6 files changed, 13 insertions(+), 15 deletions(-)
+
+commit a4f4f5ba5f64174dea931e02367aa4067d034383
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 28 08:23:36 2018 -0700
+
+    [docs] Fix titles here as well
+
+ src/hb-map.cc        | 2 +-
+ src/hb-set.cc        | 2 +-
+ src/hb-shape-plan.cc | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 213b6dd33564d0273b1db1c17a4e82548b727dfe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 18:36:24 2018 -0700
+
+    [name] Make sure hb_name_id_t is int-sized
+
+    https://github.com/harfbuzz/harfbuzz/commit/d941f66c75fe26f909b1ba248535cc372bbde851#commitcomment-31068905
+
+ src/hb-ot-name.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 4740a3593d6bbb97758593b7d5cd1b86eccbed78
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 05:07:54 2018 -0700
+
+    [docs] Divide reference API into three chapters
+
+ docs/harfbuzz-docs.xml | 213
+ +++++++++++++------------------------------------
+ 1 file changed, 56 insertions(+), 157 deletions(-)
+
+commit 1d40d72f291ed5e11850f8bd51a8562b57de1997
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 05:00:42 2018 -0700
+
+    [docs] Hook up hb-var
+
+ docs/harfbuzz-docs.xml |  1 +
+ src/hb-ot-var.cc       | 11 +++++++++++
+ 2 files changed, 12 insertions(+)
+
+commit 80d9a427cf61f61512de13cd88bdc63d881019fe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:58:32 2018 -0700
+
+    [docs] Document remaining sections
+
+ src/hb-ot-color.cc  | 10 ++++++++++
+ src/hb-ot-font.cc   | 10 ++++++++++
+ src/hb-ot-layout.cc | 10 ++++++++++
+ src/hb-ot-math.cc   | 11 +++++++++++
+ src/hb-ot-name.cc   | 10 ++++++++++
+ src/hb-ot-shape.cc  | 10 ++++++++++
+ 6 files changed, 61 insertions(+)
+
+commit cf5fa57f00613d324b55732d9e21c779ba0d2de2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:50:38 2018 -0700
+
+    [docs] Change section titles again
+
+    I think I like the uniform "hb-*" more.
+
+ src/hb-blob.cc      |  2 +-
+ src/hb-buffer.cc    |  2 +-
+ src/hb-common.cc    |  4 ++--
+ src/hb-deprecated.h | 12 ++++++++++++
+ src/hb-face.cc      |  2 +-
+ src/hb-font.cc      |  2 +-
+ src/hb-shape.cc     |  2 +-
+ src/hb-unicode.cc   |  2 +-
+ 8 files changed, 20 insertions(+), 8 deletions(-)
+
+commit 04981ee05d83ed30c9f818106589a4de9c3e9b7f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:40:43 2018 -0700
+
+    [docs] More
+
+ src/hb-coretext.cc        | 10 ++++++++++
+ src/hb-ft.cc              | 11 +++++++++++
+ src/hb-glib.cc            | 10 ++++++++++
+ src/hb-gobject-structs.cc | 12 ++++++++++++
+ src/hb-graphite2.cc       | 10 ++++++++++
+ src/hb-icu.cc             | 10 ++++++++++
+ src/hb-uniscribe.cc       | 10 ++++++++++
+ 7 files changed, 73 insertions(+)
+
+commit 5dd86aa33b4e52a0de4fcd96b2ea7bafcae8dd34
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:28:40 2018 -0700
+
+    [docs] Rename section titles to object names
+
+    More useful.
+
+ src/hb-blob.cc       | 2 +-
+ src/hb-buffer.cc     | 2 +-
+ src/hb-face.cc       | 4 ++--
+ src/hb-font.cc       | 4 ++--
+ src/hb-map.cc        | 2 +-
+ src/hb-set.cc        | 2 +-
+ src/hb-shape-plan.cc | 2 +-
+ src/hb-unicode.cc    | 2 +-
+ 8 files changed, 10 insertions(+), 10 deletions(-)
+
+commit 524fb70216d7fec17f5327237faa4d092ae15a00
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:27:36 2018 -0700
+
+    [docs] More
+
+ src/hb-map.cc | 11 ++++++++++-
+ src/hb-set.cc | 11 ++++++++++-
+ 2 files changed, 20 insertions(+), 2 deletions(-)
+
+commit 46072b7cb55bfeb8c46a78cbdb335dfdcce48298
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:21:20 2018 -0700
+
+    [ot] Fold hb-ot-tag.h into hb-ot-layout.h
+
+ docs/harfbuzz-docs.xml     |  1 -
+ docs/harfbuzz-sections.txt | 20 +++++-------
+ src/Makefile.sources       |  1 -
+ src/hb-graphite2.cc        |  2 +-
+ src/hb-ot-layout.h         | 42 ++++++++++++++++++++++++-
+ src/hb-ot-tag.h            | 78
+ ----------------------------------------------
+ src/hb-ot.h                |  1 -
+ src/hb-uniscribe.cc        |  2 +-
+ 8 files changed, 51 insertions(+), 96 deletions(-)
+
+commit 00cf4e5eb6dcb04406d5a519712da799277cec2e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:07:33 2018 -0700
+
+    [docs] Fill in some sections
+
+ docs/harfbuzz-docs.xml     | 20 ++++++--------
+ docs/harfbuzz-sections.txt | 65
+ +++++++++++++++++++---------------------------
+ src/hb-blob.cc             | 13 ++++++++++
+ src/hb-buffer.cc           |  3 ++-
+ src/hb-common.cc           | 23 ++++++++++++++++
+ src/hb-face.cc             | 13 ++++++++++
+ src/hb-font.cc             | 13 ++++++++++
+ src/hb-shape-plan.cc       | 13 ++++++++++
+ src/hb-shape.cc            |  4 ++-
+ src/hb-unicode.cc          | 14 ++++++++++
+ 10 files changed, 129 insertions(+), 52 deletions(-)
+
+commit 55a19d73b4d5e7ddd328263d241a442f16f005b2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 04:01:19 2018 -0700
+
+    Move HB_EXTERN
+
+ src/hb-common.h | 4 ++++
+ src/hb.h        | 4 ----
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 524e854c15f9d6c50c5456ae0e188f039dcf153c
+Merge: 4ee3c827 8180c37d
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 15:04:43 2018 +0330
+
+    Merge pull request #1318 from ebraminio/png
+
+    Add a non-hooked _png _svg get emoji blob
+
+commit 8180c37df0a856dbc3564c0aefd8b2acab8baf8a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 14:45:00 2018 +0330
+
+    [ot-color] Remove _png and _svg public APIs
+
+ docs/harfbuzz-sections.txt |  4 ----
+ src/dump-emoji.cc          | 11 ++++++++---
+ src/hb-ot-color.cc         | 39 +++++++++++++++++++++++++++++++++++----
+ src/hb-ot-color.h          | 24 ------------------------
+ test/api/test-ot-color.c   |  8 ++++++--
+ 5 files changed, 49 insertions(+), 37 deletions(-)
+
+commit 9aa6279a2d64ab8057b0d7acbcc77044442c6d0e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 14:24:58 2018 +0330
+
+    [ot-color/png] Try to get image blob from sbix first options.aat
+    is set
+
+ src/hb-ot-color.cc | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+commit b42661ee91ea92309e827a970f370cacc62c73aa
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 14:15:38 2018 +0330
+
+    [ot-color] Add some documentation
+
+ src/hb-ot-color.cc | 37 +++++++++++++++++++------------------
+ src/hb-ot-color.h  |  2 +-
+ 2 files changed, 20 insertions(+), 19 deletions(-)
+
+commit 4ee3c8272c31736980218cba95f97fed53d24e14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 03:18:45 2018 -0700
+
+    [docs] Fix hb_name_id_t
+
+    Yep, was not recognized without this patch!
+
+ src/hb-ot-name.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9435fb24daadf08add9a701816da01bd54c0cd78
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 13:32:14 2018 +0330
+
+    [ot-color/png] Implement CBDT part
+
+ src/hb-ot-color-cbdt-table.hh | 56
+ +++++++++++++++++++++++++++++++++++++++----
+ src/hb-ot-color.cc            | 19 ++-------------
+ src/hb-ot-color.h             |  4 ++++
+ test/api/test-ot-color.c      | 25 ++++++++++++++++---
+ 4 files changed, 79 insertions(+), 25 deletions(-)
+
+commit 9457cfd7bcc9c2fff38194f2bb82ab7be881bfeb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 03:15:34 2018 -0700
+
+    [docs] Hook up hb-map
+
+ docs/harfbuzz-docs.xml | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit d941f66c75fe26f909b1ba248535cc372bbde851
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 02:55:52 2018 -0700
+
+    [name] Make hb_name_id_t be the enum
+
+    This is like hb_script_t.
+
+    We had this exposed as unsigned int since 2.0.0 release in two APIs,
+    as well as hb_ot_layout_get_size_params() from earlier.
+    But since no one uses those (right?!), let's just fix this now.
+
+ docs/harfbuzz-docs.xml        |  6 ++++--
+ docs/harfbuzz-sections.txt    |  4 +++-
+ src/hb-ot-color-cpal-table.hh | 12 ++++++------
+ src/hb-ot-layout.cc           | 16 ++++++++--------
+ src/hb-ot-name-table.hh       |  2 +-
+ src/hb-ot-name.h              | 15 ++++-----------
+ src/test-size-params.cc       |  2 +-
+ 7 files changed, 27 insertions(+), 30 deletions(-)
+
+commit 40496a54a03864c5e6a1224c18b4b93a1f578eed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 02:49:32 2018 -0700
+
+    [name] Move HB_NAME_ID_INVALID into the enum
+
+    Don't know how to document anonymous enum members.
+
+ src/hb-ot-name.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit a8a55b9f892a5e4f086b20bbe337dc29182210af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 02:45:57 2018 -0700
+
+    [name] Move around
+
+ src/hb-ot-name.h | 74
+ ++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 37 insertions(+), 37 deletions(-)
+
+commit 3b7e5f131383956e19642d28c938f1bc0d16295f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 02:39:20 2018 -0700
+
+    [name] Rename hb_ot_name_get_names() to hb_ot_name_list_names()
+
+    And swap return value positions, so can be annotated for
+    gobject-introspectin.
+
+ docs/harfbuzz-sections.txt |  2 +-
+ src/hb-ot-name.cc          | 17 ++++++++---------
+ src/hb-ot-name.h           |  6 +++---
+ src/test-name-table.cc     |  4 ++--
+ 4 files changed, 14 insertions(+), 15 deletions(-)
+
+commit 4025ad804383dc8d5ace9654ae21d4d726d0dbc4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 02:35:06 2018 -0700
+
+    Document new API
+
+ src/hb-common.h     | 30 +++++++++++++++++++++++++-
+ src/hb-ot-color.cc  | 16 +++++++-------
+ src/hb-ot-layout.cc |  2 +-
+ src/hb-ot-name.cc   | 61
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ src/hb-ot-name.h    | 15 +++++++++++++
+ 5 files changed, 113 insertions(+), 11 deletions(-)
+
+commit 5e2a52f71a8d081441fbc1c57a3550e3a9573e46
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 12:44:33 2018 +0330
+
+    [sbix] Remove dump method from sbix accelerator
+
+ src/dump-emoji.cc             | 36 ++++++++++++++++++++++++------------
+ src/hb-ot-color-sbix-table.hh | 26 ++++++++++----------------
+ 2 files changed, 34 insertions(+), 28 deletions(-)
+
+commit 0353ac6cde47df8f5386733f5c12cc60732a5bf4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 12:24:53 2018 +0330
+
+    Fix test-name-table on older bots
+
+ src/test-name-table.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit dc11a38107ac1f0a2d3edacae33ff7f10f5e894c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 12:15:25 2018 +0330
+
+    [sbix] Set num_glyphs on accelerator
+
+    dump-emoji was broken without it
+
+ src/hb-ot-color-sbix-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 6a38fd68a8f4e66d9248e0c943ae3a1cf45c521b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 27 10:50:53 2018 +0330
+
+    [ot-color/png] sbix runtime memory check
+
+ src/hb-ot-color-cbdt-table.hh | 16 +++++++---------
+ src/hb-ot-color-sbix-table.hh | 18 ++++++++++++------
+ src/hb-ot-color-svg-table.hh  |  4 ++--
+ 3 files changed, 21 insertions(+), 17 deletions(-)
+
+commit ca645accb97841e01846e45cda32e6bd2ad15940
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 00:39:31 2018 -0700
+
+    Comment
+
+ src/hb-ot-shape-complex-indic.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 265ad408ca41e9d0b5a1056a751d834d4eadc911
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 26 23:55:11 2018 +0330
+
+    [ot-color/png] Implement sbix part
+
+ docs/harfbuzz-sections.txt    |  2 +
+ src/dump-emoji.cc             |  5 ++-
+ src/hb-ot-color-cbdt-table.hh | 27 ++++++++----
+ src/hb-ot-color-sbix-table.hh | 98
+ +++++++++++++++++++++++++++++++++++++------
+ src/hb-ot-color.cc            | 64 ++++++++++++++++++++++++++++
+ src/hb-ot-color.h             |  9 ++++
+ test/api/test-ot-color.c      | 32 ++++++++++++++
+ 7 files changed, 215 insertions(+), 22 deletions(-)
+
+commit 7f5941e162bf7806299656edafd452a47b5a55b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 27 00:06:48 2018 -0700
+
+    Remove stale comment
+
+    Ugliness was fixed in 30eab97a0072fbc22d353082249e0e6e546cd86b
+    But yeah, my smell detector was working.  Ugliness was buggy.
+
+ src/hb-ot-shape-normalize.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit e7400c0275cad4f584eeaf21ce6d5c6adca29bbb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 22:09:17 2018 -0700
+
+    [docs] Hook up new symbols
+
+ docs/harfbuzz-docs.xml     | 46
+ +++++++++++++++++++++++++++++++++++++++++-----
+ docs/harfbuzz-sections.txt | 21 +++++++++++++++++++++
+ src/hb-ot-color.cc         |  2 +-
+ 3 files changed, 63 insertions(+), 6 deletions(-)
+
+commit 6aa019c4af6b64bb732205e6051f3e73e1b70721
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 22:02:17 2018 -0700
+
+    [morx] Fix merge_cluster to end at last ligature component
+
+    Don't assume current position was a component in the ligature.
+
+ src/hb-aat-layout-morx-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 00ae4be6bf8b1d0800043167c5cf95187ac12515
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 21:59:20 2018 -0700
+
+    [morx] Fix bailing out ligation at end-of-text
+
+    Check was after a move_to, which wouldn't work.
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11147
+
+ src/hb-aat-layout-morx-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 30eab97a0072fbc22d353082249e0e6e546cd86b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 21:54:07 2018 -0700
+
+    Fix invalid memory read
+
+    Buffer might be relocated inside replace_glyphs().
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=895117
+
+ src/hb-ot-shape-normalize.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 79b2fa62ca7eb5a875778d3a2ecae63350083ba3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 21:21:18 2018 -0700
+
+    [indic] Fix infinite loop
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=863044
+
+ src/hb-ot-shape-complex-indic.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 39bd07aed5fe6ccddde53206bafceec32d56dcc1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 21:01:11 2018 -0700
+
+    Fix bunch of unused parameter warnings
+
+    Show up with gcc -O0.
+
+    There's a few more but those are functions that need to be filled in.
+
+    Maybe this is a lost battle...
+
+ src/gen-vowel-constraints.py                 |  4 ++--
+ src/hb-aat-layout-common.hh                  |  7 +++++--
+ src/hb-aat-layout-kerx-table.hh              |  4 ++--
+ src/hb-aat-layout-morx-table.hh              | 10 +++++-----
+ src/hb-face.cc                               |  2 +-
+ src/hb-font.cc                               | 29
+ ++++++++++++++--------------
+ src/hb-graphite2.cc                          |  9 ++++++---
+ src/hb-machinery.hh                          |  4 ++--
+ src/hb-ot-color-cbdt-table.hh                |  2 +-
+ src/hb-ot-glyf-table.hh                      |  4 ++--
+ src/hb-ot-hmtx-table.hh                      |  2 +-
+ src/hb-ot-layout-gpos-table.hh               |  2 +-
+ src/hb-ot-math-table.hh                      |  2 +-
+ src/hb-ot-maxp-table.hh                      |  2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh   |  6 +++---
+ src/hb-ot-shape-complex-arabic.cc            |  6 +++---
+ src/hb-ot-shape-complex-hangul.cc            |  2 +-
+ src/hb-ot-shape-complex-khmer.cc             |  2 +-
+ src/hb-ot-shape-complex-myanmar.cc           |  6 +++---
+ src/hb-ot-shape-complex-use.cc               |  8 ++++----
+ src/hb-ot-shape-complex-vowel-constraints.cc |  4 ++--
+ src/hb-ot-shape-fallback.cc                  |  4 ++--
+ src/hb-ot-shape-normalize.cc                 |  4 +++-
+ src/hb-ot-shape.cc                           |  2 +-
+ src/hb-ot-tag.cc                             |  3 +--
+ src/hb-ot-vorg-table.hh                      |  2 +-
+ src/hb-set.cc                                |  2 +-
+ src/hb-shape-plan.cc                         |  2 +-
+ src/hb-utf.hh                                |  2 +-
+ 29 files changed, 73 insertions(+), 65 deletions(-)
+
+commit b2e1ec374cbd2a6e4d79419bd5601a4e2ecb9864
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 20:45:28 2018 -0700
+
+    [subset] Fix warning
+
+ src/hb-subset.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 337ea0b7175793305e9d8935aecf385b707a5bc4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 20:31:14 2018 -0700
+
+    [fuzzing] Remove HB_NDEBUG
+
+    Not sure why it ever was added.
+
+ src/Makefile.am | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 12058e44d100c28816f42c91c63a0f960a662181
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 16:23:50 2018 -0700
+
+    [fuzzing] Add more test
+
+ ...z-testcase-minimized-harfbuzz_fuzzer-5659690013556736 | Bin 0 ->
+ 2732 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit c965eeadbc71943f2336a20dc16ac691c805b90e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 13:43:25 2018 -0700
+
+    [name] Default to "en" if language is not specified
+
+ src/hb-ot-name.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 3fd6e5dbefe52a4a2e604c28a4edfbd40ed16027
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 13:42:38 2018 -0700
+
+    [name] Add pre-defined nameIDs
+
+ src/hb-ot-name.h | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+commit 20d0171d20cf9f3f93bdd6878bbc1d7d8329e75f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 13:20:19 2018 -0700
+
+    [name] Fill out most missing language codes
+
+ src/hb-ot-name-language.cc | 114
+ +++++++++++++++++++++++----------------------
+ 1 file changed, 58 insertions(+), 56 deletions(-)
+
+commit 622b014faf7bbe7a97f9aff959c434d1664c10d0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 12:40:15 2018 -0700
+
+    [name] Skip enumerating names with unknown language
+
+ src/hb-ot-name-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 2c39f359e4a7312e3b518f76815d79e42ee96a32
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 12:34:30 2018 -0700
+
+    [utf] Remove unused typedef
+
+ src/hb-utf.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit ce81c7429810ad3902c37e50016ca54b9bae6f91
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 12:34:03 2018 -0700
+
+    [utf] Fix ASCII
+
+ src/hb-utf.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 327546e633b590d6dedfb901810ccf490a0bf922
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 23:33:44 2018 -0700
+
+    [name] Hook up ltag table
+
+ src/hb-aat-layout.cc     | 15 ++++++++++++++-
+ src/hb-aat-layout.hh     |  5 +++++
+ src/hb-aat-ltag-table.hh | 17 +++++++++++++++--
+ src/hb-ot-face.hh        |  3 ++-
+ src/hb-ot-name-table.hh  |  9 +++++----
+ 5 files changed, 41 insertions(+), 8 deletions(-)
+
+commit dc9a5f88b401fcad598946fcf735010c563741ac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 23:16:06 2018 -0700
+
+    [name] Do record sanitization at run-time
+
+ src/hb-dsalgs.hh        | 62
+ +++++++++++++++++++++++++++----------------------
+ src/hb-ot-name-table.hh | 22 +++++++++++-------
+ src/hb-ot-name.cc       |  2 +-
+ 3 files changed, 49 insertions(+), 37 deletions(-)
+
+commit a53d301b1c9f72cb42cc0fc321e2ad4dbac8e064
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 23:05:55 2018 -0700
+
+    [name] Minor
+
+ src/hb-ot-name-table.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit c442fd9a10b3e91ab18720188afff08325adf6dc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 22:45:45 2018 -0700
+
+    [name] Add src/test-name-table tool to show all font names
+
+ src/Makefile.am        | 17 ++++++++-----
+ src/test-name-table.cc | 67
+ ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 78 insertions(+), 6 deletions(-)
+
+commit 7007bd9dff9f8eef3263f1b39327552ff1ebae3f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 22:44:36 2018 -0700
+
+    [name] Rebuild language list, include missing entries
+
+ src/hb-ot-name-language.cc | 634
+ ++++++++++++++++++++++++++-------------------
+ 1 file changed, 370 insertions(+), 264 deletions(-)
+
+commit 68f172101c1228a7d669d71da1d0eeb96a10565e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 22:19:09 2018 -0700
+
+    [name] Fix cmp for invalid language
+
+ src/hb-ot-name-table.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 888a65615c7b11222749ae85c124aaa9a36fe863
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 22:16:32 2018 -0700
+
+    [name] Fix nul-termination bug
+
+ src/hb-ot-name.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9b532e2ed432611005b19c40cac7e626afcccd08
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 22:00:19 2018 -0700
+
+    [name] Add language mapping
+
+ src/Makefile.sources       |   2 +
+ src/hb-ot-name-language.cc | 349
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-name-language.hh |  40 ++++++
+ src/hb-ot-name-table.hh    |  21 ++-
+ 4 files changed, 399 insertions(+), 13 deletions(-)
+
+commit e2f9b657758cda3708c0a9db971c467ca59d5c19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 21:19:56 2018 -0700
+
+    [name] Start adding language support
+
+ src/hb-ot-name-table.hh | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+commit 6db6bbe64bd63554919647c5b527e03aedbaee4e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 21:12:58 2018 -0700
+
+    [name] Remove unused cmp function
+
+ src/hb-ot-name-table.hh | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+commit 4668a05006e6c4797df19651489b4589817e1e01
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 20:51:53 2018 -0700
+
+    [name] Hook things up
+
+    Accept Mac Latin name entries as ASCII as well.
+
+ src/hb-ot-name-table.hh | 24 +++++++++++++++------
+ src/hb-ot-name.cc       |  8 +++++--
+ src/hb-utf.hh           | 55
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 79 insertions(+), 8 deletions(-)
+
+commit 69f5da0629f1e5a307fc49fe58490aa92d1bd0e2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 20:30:40 2018 -0700
+
+    [name] More
+
+    It assumes all names are encoded in UTF16-BE.  Other than that,
+    and not
+    listing languages correctly, it's *supposed* to work.
+
+ src/hb-dsalgs.hh                | 21 +++++++++++++++++++++
+ src/hb-ot-name-table.hh         | 37
+ ++++++++++++++++++++++++++++++-------
+ src/hb-ot-name.cc               | 12 ++++++++----
+ src/hb-ot-os2-unicode-ranges.hh | 10 +++++-----
+ src/hb-unicode.cc               |  8 ++++----
+ src/hb-unicode.hh               |  2 +-
+ 6 files changed, 69 insertions(+), 21 deletions(-)
+
+commit 64334aff8c2ea5aa066d77a95844bc6f84efe725
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 20:15:53 2018 -0700
+
+    [name] Fix check
+
+ src/hb-ot-name.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5531bd068e759a5acb3b8d301c0ff9c64844166e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 20:04:05 2018 -0700
+
+    [name] Flesh out UTF-X to UTF-X conversion routines
+
+ src/hb-ot-name.cc |  84 ++++++++++++++++++++++++++++++++++++------
+ src/hb-ot-name.h  |  10 ++---
+ src/hb-utf.hh     | 107
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 182 insertions(+), 19 deletions(-)
+
+commit 84811a06a26508effe9f4a9eaf1be15297ecf0cb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 03:16:03 2018 -0700
+
+    [name] Fix for rebase changes to hb_array_t
+
+ src/hb-ot-name-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 1046b1938b16ab6be861b0828b446fa13cf0377b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 05:42:23 2018 -0700
+
+    [name] Some more
+
+ src/hb-ot-name.cc | 19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+commit b4d4d1ea787c829dea023d99f974a38bdc3de0ae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 19:55:17 2018 -0700
+
+    [name] Return full string length from API
+
+ src/hb-ot-name.cc | 6 +++---
+ src/hb-ot-name.h  | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit 8d304ef7f9094a71fabc3efd87b37a030c437adf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 19:04:48 2018 -0700
+
+    [utf] Add UTF16-BE and UTF32-BE
+
+ src/hb-buffer.cc |  4 +--
+ src/hb-utf.hh    | 80
+ ++++++++++++++++++++++++++++++++------------------------
+ 2 files changed, 48 insertions(+), 36 deletions(-)
+
+commit a826a8730f21ae996ae8f4d12c44dc18b9e8e933
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 13:06:56 2018 -0700
+
+    [name] Hide internal details from public API
+
+ src/hb-ot-name-table.hh | 23 +++++++++++++----------
+ src/hb-ot-name.h        |  3 +--
+ 2 files changed, 14 insertions(+), 12 deletions(-)
+
+commit e7c595a9f09ba1552b2de1f8d56cbdcf376b9cad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 23:34:54 2018 -0700
+
+    [name] More
+
+ src/hb-ot-name.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 75cd8c86bd9b0973864bb92e0244bf038980765e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 23:32:08 2018 -0700
+
+    [name] Add hb_ot_name_get_utf()
+
+ src/hb-ot-name.cc | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+commit c783d36324dd1e2031d3387064afab1ce5d90b6f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 23:28:49 2018 -0700
+
+    [name] Pre-allocate array
+
+ src/hb-ot-name-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c2aa409537c3e8a7b8592ef90f8304bd6588561d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 23:09:28 2018 -0700
+
+    [name] Start implementing hb_ot_name_get_utf16()
+
+ src/hb-ot-name-table.hh |  6 ++++--
+ src/hb-ot-name.cc       | 22 ++++++++++++++++++++++
+ src/hb-ot-name.h        |  8 ++++++--
+ 3 files changed, 32 insertions(+), 4 deletions(-)
+
+commit 740cde8991283b8b4e1e77e022175251eb37d3d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 23:00:27 2018 -0700
+
+    [name] Implement hb_bytes_t get_name()
+
+ src/hb-ot-name-table.hh | 24 +++++-------------------
+ 1 file changed, 5 insertions(+), 19 deletions(-)
+
+commit c3425f2401dffb1f3b5bd6fdbc0c3e9aad0f4306
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:53:40 2018 -0700
+
+    [name] Add hb-ot-name.cc for realz
+
+ src/hb-ot-name.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+commit 90420ed8cb297f1ceff75f5a75c8fa7b6ea6f65e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:48:48 2018 -0700
+
+    [name] Implement hb_ot_name_get_names()
+
+ src/Makefile.sources    | 1 +
+ src/hb-ot-name-table.hh | 3 +--
+ src/hb-ot-name.h        | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+commit 9a6c87c17d51fd57e4225c776a0fabbfd313f4f4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:42:04 2018 -0700
+
+    [name] Finish accelerator sorting
+
+ src/hb-ot-name-table.hh | 61
+ +++++++++++++++++++++++++++++++++++++++++--------
+ src/hb-ot-name.h        |  3 ++-
+ 2 files changed, 53 insertions(+), 11 deletions(-)
+
+commit 2157e56b34e7b932dd144ee3563f5bd682bbed30
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:22:50 2018 -0700
+
+    [name] Start implementing public API infrastructure
+
+ src/hb-ot-face.cc       |  1 +
+ src/hb-ot-face.hh       |  7 +++---
+ src/hb-ot-name-table.hh | 60
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-name.h        |  3 +++
+ 4 files changed, 68 insertions(+), 3 deletions(-)
+
+commit 0bf93ec0fb549d838b0a246de02a95559a9b2772
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 21:34:10 2018 -0700
+
+    [name] Add public API declarations
+
+ src/hb-ot-name.h | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+commit 982c2f4a65d127e56e09e7ab583f84099b8136bb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 26 15:40:12 2018 -0700
+
+    [indic/khmer/myanmar/use] Clarify clear_syllable
+
+    No logic change.
+
+ src/hb-ot-shape-complex-indic.cc   |  3 ++-
+ src/hb-ot-shape-complex-khmer.cc   |  4 +---
+ src/hb-ot-shape-complex-myanmar.cc | 40
+ ++++++++++++++++++--------------------
+ src/hb-ot-shape-complex-use.cc     | 22 +++++++++++++++------
+ 4 files changed, 38 insertions(+), 31 deletions(-)
+
+commit 143ffe65aa7f20d6c53219905cbc2520d680b8dd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 26 12:14:30 2018 +0330
+
+    [fuzz] Add a new testcase
+
+ ...z-testcase-minimized-hb-shape-fuzzer-5658272078495744 | Bin 0 ->
+ 2252 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 30f18039b3c0e5748101f8934ae82aebfc5a83f7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 26 09:34:34 2018 +0330
+
+    [svg] Rename _svg_create_blob to _glyph_reference_blob_svg
+
+ docs/harfbuzz-sections.txt | 2 ++
+ src/dump-emoji.cc          | 2 +-
+ src/hb-ot-color.cc         | 4 ++--
+ src/hb-ot-color.h          | 2 +-
+ test/api/test-ot-color.c   | 6 +++---
+ 5 files changed, 9 insertions(+), 7 deletions(-)
+
+commit 5cb1ce868138a10c0663a18c3891bc717aa4bc64
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 25 22:39:58 2018 +0330
+
+    [svg] Collapse SVGDocumentIndex into SVG
+
+ src/hb-ot-color-svg-table.hh | 54
+ +++++++++++++++-----------------------------
+ src/hb-ot-color.cc           |  2 +-
+ test/api/test-ot-color.c     |  2 +-
+ 3 files changed, 20 insertions(+), 38 deletions(-)
+
+commit 4ceabb8c2126fe365303b8d69e667005276c0241
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 25 21:52:35 2018 +0330
+
+    [svg] Hide start_glyph and end_glyph from API
+
+ src/dump-emoji.cc            | 21 ++++++++-------------
+ src/hb-ot-color-svg-table.hh | 42
+ ++++++++++++------------------------------
+ src/hb-ot-color.cc           |  9 ++-------
+ src/hb-ot-color.h            |  5 +----
+ test/api/test-ot-color.c     | 11 ++---------
+ 5 files changed, 25 insertions(+), 63 deletions(-)
+
+commit c7a4e3dfb5c8dd4f8faf08e327bb1900c0096cf6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 23 18:00:48 2018 +0330
+
+    [svg] Add public API
+
+    * hb_ot_color_has_svg
+    * hb_ot_color_glyph_svg_create_blob
+
+ src/dump-emoji.cc             | 51 +++++++++++++++----------
+ src/hb-open-type.hh           |  1 -
+ src/hb-ot-color-sbix-table.hh |  2 +
+ src/hb-ot-color-svg-table.hh  | 86
+ ++++++++++++++++++++++++++++++++-----------
+ src/hb-ot-color.cc            | 53 ++++++++++++++++++++++----
+ src/hb-ot-color.h             | 13 +++++++
+ src/hb-ot-face.cc             |  2 +
+ src/hb-ot-face.hh             |  4 +-
+ src/hb-ot-layout.cc           |  4 --
+ test/api/test-ot-color.c      | 43 +++++++++++++++++++---
+ 10 files changed, 199 insertions(+), 60 deletions(-)
+
+commit e98af6d1eda33346f72de8a45fbd317fc0e15935
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 22:25:29 2018 -0700
+
+    [layout] Try to speed up collect_lookups some more
+
+    Barely made a dent :(.
+
+ src/hb-ot-layout-common.hh |  2 ++
+ src/hb-ot-layout.cc        | 23 ++++-------------------
+ 2 files changed, 6 insertions(+), 19 deletions(-)
+
+commit eb44bfc864f91c0c833c3156475d191ac1b79c72
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 21:42:19 2018 -0700
+
+    [layout] Memoize collect_features
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1317
+    Fixes https://oss-fuzz.com/v2/testcase-detail/6543700493598720
+
+ src/hb-ot-layout.cc | 55
+ ++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 48 insertions(+), 7 deletions(-)
+
+commit 84098b1639775aea5bf3f5d91fa6e657b612ce3a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 21:33:12 2018 -0700
+
+    [layout] Remove unintentionally added code
+
+ src/hb-ot-layout-common.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 941600a9e06309f148d51403fa07dc56ce542572
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 21:26:08 2018 -0700
+
+    [layout] Add hb_collect_features_context_t
+
+    Towards https://github.com/harfbuzz/harfbuzz/pull/1317
+
+ src/hb-ot-layout.cc | 66
+ +++++++++++++++++++++++++++++------------------------
+ 1 file changed, 36 insertions(+), 30 deletions(-)
+
+commit c237cdfcc74d33f77b2399b4d08228c2fcf50df5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 21:17:30 2018 -0700
+
+    [lookup] Fold another function inline
+
+ src/hb-ot-layout.cc | 48 +++++++++++++++++++++---------------------------
+ 1 file changed, 21 insertions(+), 27 deletions(-)
+
+commit fe5520ddea3941f7a72888d908fd2b895e2f388e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 20:58:34 2018 -0700
+
+    [layout] More prep work to memoize collect_features() work
+
+ src/hb-ot-layout.cc | 62
+ ++++++++++++++++++++---------------------------------
+ 1 file changed, 23 insertions(+), 39 deletions(-)
+
+commit e8e67503ff0a50eb10ad410d6a76a282ea494cf4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 20:48:20 2018 -0700
+
+    [lookup] More prep work for memoizing collect_features
+
+    https://github.com/harfbuzz/harfbuzz/pull/1317
+
+ src/hb-ot-layout-common.hh |  2 ++
+ src/hb-ot-layout.cc        | 83
+ +++++++++++++++++++++-------------------------
+ 2 files changed, 40 insertions(+), 45 deletions(-)
+
+commit 96828b97a8fc2c50721ce040bdde63c462908791
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 20:34:29 2018 -0700
+
+    [layout] Minor
+
+    We were returning the accelerator's lookup count.  Returns table's.
+    They are the same except for OOM cases.  Just shorter code.
+
+ src/hb-ot-layout.cc | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+commit 73449cd213c3a12468e99b9c3d840fc60a334902
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 20:32:05 2018 -0700
+
+    [layout] Fold one function inline
+
+    Preparation for fixing https://github.com/harfbuzz/harfbuzz/pull/1317
+
+ src/hb-ot-layout.cc | 22 +++-------------------
+ 1 file changed, 3 insertions(+), 19 deletions(-)
+
+commit ba5ca6a762cb46a17f41673b14996a12e6cfe3d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 17:41:26 2018 -0700
+
+    [morx] Use deleted-glyph, instead of actual deletion, in Ligation
+
+    Closer to what CoreText does.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1302
+
+ src/hb-aat-layout-morx-table.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 5c272e3613667ca532f32764824784c63d797f57
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 17:36:33 2018 -0700
+
+    [morx] Remove deleted-glyph at the end of processing
+
+ src/hb-aat-layout-morx-table.hh | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+commit 1bb8ed86d6cfec0fc87c8e1930d9a86426b42001
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 17:33:48 2018 -0700
+
+    [aat] Minor
+
+ src/hb-aat-layout-common.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 102af615f15d04da20c17d80eb38f5948020f9ac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 17:29:32 2018 -0700
+
+    [aat] Start adding support for DELETED-GLYPH
+
+    https://github.com/harfbuzz/harfbuzz/issues/1302
+
+ src/hb-aat-layout-common.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 955aa56b11e4fa14bc6d5b1b56cb810e28fab6cd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 16:50:38 2018 -0700
+
+    [vector] Make it act more like pointer
+
+    Add pointer cast operator and plus operator.
+
+ src/hb-coretext.cc      |  2 +-
+ src/hb-machinery.hh     |  2 +-
+ src/hb-ot-cmap-table.hh |  2 +-
+ src/hb-set.hh           |  8 ++++----
+ src/hb-subset.cc        |  2 +-
+ src/hb-uniscribe.cc     | 12 ++++++------
+ src/hb-vector.hh        |  6 ++++++
+ 7 files changed, 20 insertions(+), 14 deletions(-)
+
+commit 8d55e2adef9a376a5cf83c20aff2dba27dd64da8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 16:37:53 2018 -0700
+
+    [set] Minor
+
+ src/hb-set.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 64c32edfe18f5ef3b348e5c84077ee1f6faf4f48
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 16:35:36 2018 -0700
+
+    [set] Make array access more explicit
+
+    Follow up on 94e421abbfc7ede9aaf3c8d86bb0ff9992ea3123
+
+ src/hb-set.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit e3ceb2dde3525824de68914e12ad4e8a873ab90a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 14:30:24 2018 -0700
+
+    Fix again
+
+ test/shaping/data/in-house/fonts/DFONT.dfont | Bin 0 -> 3505 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit eceeb85666814023f57ee3517bbb304830a60c55
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 26 00:23:45 2018 +0330
+
+    [docs] Add hb-ot-color section
+
+ docs/harfbuzz-sections.txt | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+commit be746009e9b7063dcb57e30e342f9410387ef8b6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 25 13:40:40 2018 -0700
+
+    dropped support of legacy CFF CharString ops
+
+    along with test & font
+
+ src/hb-cff1-interp-cs.hh          | 135
+ +-------------------------------------
+ test/api/fonts/cff1_legacyops.otf | Bin 3104 -> 0 bytes
+ test/api/test-ot-extents-cff.c    |  23 -------
+ 3 files changed, 1 insertion(+), 157 deletions(-)
+
+commit 1cfe702872058ebc50d6cb5543daa38fb3a7ebfb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 13:37:08 2018 -0700
+
+    Fixup
+
+ test/shaping/data/in-house/fonts/{TRAK.tff => TRAK.ttf} | Bin
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 5739c876d0d080e7feaefd323245702c663f33be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 13:23:33 2018 -0700
+
+    [test] Rename some fonts
+
+    If we have duplicae font files in different directories, that would
+    break the oss-fuzz build currently.  So, rename some to avoid
+    name class with text-rendering-test.  Would be better to find
+    another solution.
+
+ ...TestMORXTwentyeight.ttf => MORXTwentyeight.ttf} | Bin
+ .../data/in-house/fonts/{TestTRAK.ttf => TRAK.tff} | Bin
+ .../data/in-house/fonts/{TestTTC.ttc => TTC.ttc}   | Bin
+ test/shaping/data/in-house/fonts/TestDFONT.dfont   | Bin 3505 -> 0 bytes
+ test/shaping/data/in-house/tests/aat-morx.tests    |   2 +-
+ test/shaping/data/in-house/tests/aat-trak.tests    |  22
+ ++++++++++-----------
+ test/shaping/data/in-house/tests/collections.tests |  12 +++++------
+ 7 files changed, 18 insertions(+), 18 deletions(-)
+
+commit 21ede867df28d1214ca677a24ac65ab0b7e95f42
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 25 13:19:34 2018 -0700
+
+    Fix possible overflow in bsearch impls
+
+    From bungeman.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1314
+
+ src/hb-dsalgs.hh               | 2 +-
+ src/hb-open-type.hh            | 4 ++--
+ src/hb-ot-cmap-table.hh        | 2 +-
+ src/hb-ot-layout-gpos-table.hh | 2 +-
+ src/hb-vector.hh               | 2 +-
+ 5 files changed, 6 insertions(+), 6 deletions(-)
+
+commit 2ebf36010206cebdbe58bab6edf4e3bc011b6479
+Merge: 36c2c374 94e421ab
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 25 13:05:06 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 94e421abbfc7ede9aaf3c8d86bb0ff9992ea3123
+Author: Ben Wagner <bungeman@chromium.org>
+Date:   Thu Oct 25 13:44:27 2018 -0400
+
+    Remove some use of Crap in hb-set.
+
+    When hb_set_t::page_for_insert needs to insert at the end of the
+    page_map
+    it ends up evaluating '&page_map[i + 1]' which has hb_vector return an
+    lvalue of a Crap so that nothing can be moved to its address. This
+    turns
+    into issues with ThreadSanitizer on Crap when two threads modify
+    different
+    hb_set_t instances. This can be avoided by using '&page_map[i] + 1'
+    instead.
+
+ src/hb-set.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2798ac1c28edc4ba6f2283784d1027393f588f8c
+Author: azure-pipelines[bot]
+<azure-pipelines[bot]@users.noreply.github.com>
+Date:   Thu Oct 25 15:22:54 2018 +0000
+
+    Set up CI with Azure Pipelines
+
+ azure-pipelines.yml | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+commit 9a830a17318446dab86e1439f7167d8a698eb856
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Thu Oct 25 01:55:10 2018 +0200
+
+    [appveyor] Drop Cygwin builds again
+
+    They are so slow and we had only a couple of Cygwin build failure
+    reported in ~5 years.
+
+ appveyor.yml | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+commit 00e51a10832965f4c1d65a6d71c9582782f02c2b
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Wed Oct 24 22:58:22 2018 +0200
+
+    [appveyor] Limit make to three jobs
+
+    https://github.com/harfbuzz/harfbuzz/pull/1309#issuecomment-432778270
+
+ appveyor.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit ae9e8f292b2ad79b01776ae5785a94afbfc4b3e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 24 16:46:07 2018 -0700
+
+    [vowel-constraints] Reset continuation on all dottedcircles
+
+    One of the was missed before.  Not intentional.
+
+ src/gen-vowel-constraints.py                 | 9 +++++++--
+ src/hb-ot-shape-complex-vowel-constraints.cc | 9 +++++++--
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+commit d2b20ba18dfe3fe507ee7cb64fd73e3f1e1e5ae0
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Wed Oct 24 11:37:09 2018 +0200
+
+    [appveyor] Build on Cygwin and msys2 in parallel
+
+ appveyor.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0d2fa7fd4c4df0dcf7800b1267d1126e5a4b1ab1
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Wed Oct 24 11:23:21 2018 +0200
+
+    [appveyor] Do not update msys2
+
+    Looks like AppVeyor has new enough packages for our needs. Cuts
+    CI build
+    time by 5 minutes.
+
+ appveyor.yml | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 6a3ad245609ce8496d08404b28217dca8d01c10b
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Wed Oct 24 09:49:08 2018 +0200
+
+    [appveyor] Organize config file a bit
+
+ appveyor.yml | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 0cd7d041d83ae28e8c7d8a156750464af76de291
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Wed Oct 24 09:43:10 2018 +0200
+
+    [appveyor] Don’t build branches with open PR twice
+
+ appveyor.yml | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 401cdf07922f66c762dabfd8e3d45c35e33de7c0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 17:00:49 2018 -0700
+
+    [ot-font] Fix sign of ascent/descent
+
+    Some fonts, like msmincho, have positive number as descent
+    in vhea table.  That's wrong.  Just enforce sign on ascent/descent
+    when reading both horizontal and vertical metrics.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1248
+
+ src/hb-ot-hmtx-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit ba502dea1e81981f3893b5353400909bf60e354f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 16:46:10 2018 -0700
+
+    [morx] Fix cluster-merging when ligating
+
+    Only merge when actual ligature happened.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1305
+
+ src/hb-aat-layout-morx-table.hh                          |   7 ++++---
+ test/shaping/data/in-house/Makefile.sources              |   1 +
+ test/shaping/data/in-house/fonts/TestMORXTwentyeight.ttf | Bin 0 ->
+ 2660 bytes
+ test/shaping/data/in-house/tests/aat-morx.tests          |   1 +
+ 4 files changed, 6 insertions(+), 3 deletions(-)
+
+commit aa5af8d041521507f8bc8ded8a365ee56098388c
+Author: Garret Rieger <grieger@google.com>
+Date:   Tue Oct 23 15:45:35 2018 -0700
+
+    Fix size calculation in DEFINE_SIZE_ARRAY_SIZED.
+
+ src/hb-machinery.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 36c2c374bf9c2d0ca903e601760e69bfc3da5388
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 23 15:11:09 2018 -0700
+
+    removed unused multi_val from DictVal
+
+ src/hb-cff-interp-common.hh      | 16 ----------------
+ src/hb-cff-interp-dict-common.hh |  3 ---
+ src/hb-ot-cff1-table.hh          |  2 +-
+ src/hb-ot-cff2-table.hh          |  1 -
+ 4 files changed, 1 insertion(+), 21 deletions(-)
+
+commit f33ad6d69216a983624e832177895481549bdc07
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 14:31:51 2018 -0700
+
+    [aat] Fix up previous commit and add files
+
+ src/hb-aat-map.cc  |  62 +++++++++++++++++++++++++++++++
+ src/hb-aat-map.hh  | 106
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-map.cc   |   1 +
+ src/hb-ot-shape.cc |  15 ++++++--
+ 4 files changed, 181 insertions(+), 3 deletions(-)
+
+commit ffe347844803a6a9036d8357b744a982f5e5a6c9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 14:14:03 2018 -0700
+
+    [aat] Allow enabling/disabling features
+
+    Only works at entire-buffer range, not sub-ranges.
+
+    Test with:
+
+    $ hb-shape Zapfino.dfont Zapfino
+    [Z_a_p_f_i_n_o=0+2333]
+
+    $ hb-shape Zapfino.dfont Zapfino --features=-dlig
+    [Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|o=6+250]
+
+    $ hb-shape Zapfino.dfont Zapfino --features=+dlig
+    [Z_a_p_f_i_n_o=0+2333]
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1303
+
+ src/Makefile.sources            |  2 ++
+ src/hb-aat-layout-morx-table.hh | 29 +++++++++++++++++++++++++----
+ src/hb-aat-layout.cc            |  8 ++++++++
+ src/hb-aat-layout.hh            |  3 +++
+ src/hb-ot-shape.cc              |  4 ++++
+ src/hb-ot-shape.hh              |  5 +++++
+ 6 files changed, 47 insertions(+), 4 deletions(-)
+
+commit 8be0e5fd4540b18e26b28b414bd99af3bb1548b1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 13:39:50 2018 -0700
+
+    [ot-map] Minor
+
+ src/hb-ot-map.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e8fccbc36b2cc5e1c9f218c83cad7f606c03e7a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 13:25:03 2018 -0700
+
+    Minor
+
+ src/hb-ot-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 76324d95caa4b83cd4b515f516c2d3674455ea5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 13:09:30 2018 -0700
+
+    Shift code around
+
+ src/hb-ot-shape.cc | 18 ++++++++++--------
+ src/hb-ot-shape.hh |  9 +++------
+ 2 files changed, 13 insertions(+), 14 deletions(-)
+
+commit e1241636d60a63cbfd741288716b55797a4dc8ee
+Merge: 960267fc cf92d657
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 23 11:25:51 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit cf92d6579e91d326598dcff93457fe85dfa962c2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 03:10:56 2018 -0700
+
+    [trak] Allow disabling tracking for ranges of text
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1303
+
+ src/hb-aat-layout-trak-table.hh                 |  4 ++++
+ src/hb-ot-shape.cc                              | 11 +++++++----
+ src/hb-ot-shape.hh                              |  5 ++++-
+ test/shaping/data/in-house/tests/aat-trak.tests |  1 +
+ 4 files changed, 16 insertions(+), 5 deletions(-)
+
+commit 8869436cb8a338b46c138305966a4b7b2c3ee374
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 03:07:48 2018 -0700
+
+    When parsing feature ranges, accept ';' instead of ':'
+
+ src/hb-common.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 22ecefd88e1ea1841f363057b948aa792ac871a6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 23 00:52:05 2018 +0330
+
+    Make tracking optout possible using 'trak' ot feature
+
+    So '--features=-trak' or 'font-feature-settings: 'trak' 0;'
+    can prevent
+    applying of tracking if used.
+
+ src/hb-ot-shape.cc                              | 10 +++++++---
+ test/shaping/data/in-house/tests/aat-trak.tests |  2 ++
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+commit 6d40eb8372a2c74a6e1294b44a2b19c99d11e7da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 02:51:42 2018 -0700
+
+    Touch up on previous commit
+
+    https://github.com/harfbuzz/harfbuzz/pull/1273
+
+ src/HBIndicVowelConstraints.txt              |  97 ++++++
+ src/Makefile.am                              |   6 +-
+ src/Makefile.sources                         |   1 +
+ src/gen-vowel-constraints.py                 | 124 ++------
+ src/hb-ot-shape-complex-indic.cc             |  10 +-
+ src/hb-ot-shape-complex-use.cc               |  11 +-
+ src/hb-ot-shape-complex-vowel-constraints.cc | 433
+ ++++++++++++++++++++++++++
+ src/hb-ot-shape-complex-vowel-constraints.hh | 447
+ ++-------------------------
+ 8 files changed, 606 insertions(+), 523 deletions(-)
+
+commit 205737acdc268b1c90cf00bde2d2038519a8bf48
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Oct 12 16:54:54 2018 -0400
+
+    [use] Prohibit visually ambiguous vowel sequences
+
+ src/Makefile.am                                    |   7 +-
+ src/Makefile.sources                               |   1 +
+ src/gen-vowel-constraints.py                       | 286 ++++++++++++++
+ src/hb-ot-shape-complex-indic.cc                   | 272 +------------
+ src/hb-ot-shape-complex-use.cc                     |   3 +-
+ src/hb-ot-shape-complex-vowel-constraints.hh       | 434
+ +++++++++++++++++++++
+ test/shaping/README.md                             |   4 +-
+ .../46669c8860cbfea13562a6ca0d83130ee571137b.ttf   | Bin 0 -> 7184 bytes
+ .../in-house/tests/use-vowel-letter-spoofing.tests |  94 +++++
+ 9 files changed, 827 insertions(+), 274 deletions(-)
+
+commit 48ed598a356983f4623029dd5e87254fb59e3691
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 02:19:32 2018 -0700
+
+    [VORG] Hook up to hb-ot-font's v_origin
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/544
+
+    Test added with NotoSansCJK, eg. with U+FF38.
+
+ src/hb-ot-face.cc                                        |   1 -
+ src/hb-ot-font.cc                                        |  11
+ +++++++++--
+ src/hb-ot-vorg-table.hh                                  |   6 ++++--
+ .../fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf   | Bin 0 ->
+ 2808 bytes
+ test/shaping/data/in-house/tests/vertical.tests          |   1 +
+ 5 files changed, 14 insertions(+), 5 deletions(-)
+
+commit 097ecfd4a991d4fa306bab7330d9952966e94d1f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 02:09:42 2018 -0700
+
+    [VORG] Add get_y_origin()
+
+    Unhooked.
+
+ src/hb-ot-vorg-table.hh | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+commit 6fb24d5e3e0cf61c0ed3574e5bcf4598a13d6b69
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 01:58:59 2018 -0700
+
+    [VORG] Add VORG table
+
+    Cherry-picked from cff-subset branch.
+
+ src/Makefile.sources    |   1 +
+ src/hb-ot-face.cc       |   1 +
+ src/hb-ot-face.hh       |   1 +
+ src/hb-ot-vorg-table.hh | 168
+ ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 171 insertions(+)
+
+commit 531f9822b2e8a60f03c43d6f86ef9ed32c951f0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 01:32:08 2018 -0700
+
+    [morx] Add a few debug messages to Ligature chain
+
+ src/hb-aat-layout-morx-table.hh | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+commit 0e5bcdef7fb592f986ad5b4e07b80d2efb5e3344
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 23 00:39:44 2018 -0700
+
+    [morx] Clear stack upon underflow when acting ligatures
+
+ src/hb-aat-layout-morx-table.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 1bfb96a9c8d7653f0dee5c5fab3c6e85cea900cd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 23:41:47 2018 -0700
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   2 +-
+ .../data/text-rendering-tests/fonts/TestTRAKOne.ttf      | Bin 0 ->
+ 1752 bytes
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 792071de4075cb9af0793f0d7c70da0780923bb6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 23:38:34 2018 -0700
+
+    [morx] Leave ligature on stack after ligating
+
+    Test with Apple Color Emoji.ttf of ~66MB and following sequence:
+
+    ./hb-shape Apple\ Color\ Emoji-old.ttf --font-funcs=ot -u
+    U+1F468,200d,U+1F469,200d,U+1F467,200d,1f466
+
+    Should form full family if matching works correctly.  It first makes
+    family of three, then makes family of four out of that and the last
+    two characters.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1292
+
+ src/hb-aat-layout-morx-table.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit e1b8e933f099efae3c3e1f5706be19120b44de20
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 23 09:23:48 2018 +0330
+
+    [ci] Disable llvm-gcc
+
+      #define Null(Type) Null<typename hb_remove_const<typename
+      hb_remove_reference<Type>::value>::value>()
+
+    raises:
+      hb-blob.cc: In function 'hb_blob_t* hb_blob_get_empty()':
+      hb-blob.cc:194: error: using 'typename' outside of template
+      hb-blob.cc:194: error: using 'typename' outside of template
+
+    Removing "typename"s fixes the issue but makes newer compiler fail
+    apparently.
+
+    Probably downstream can patch that locally till we get a solution.
+
+ .circleci/config.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8c78ced95b639730efd0edc521e4e81ad50af501
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 21:49:42 2018 -0700
+
+    Unbreak builds
+
+ src/hb-dsalgs.hh    | 2 +-
+ src/hb-open-type.hh | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 8d689f8a7bccda861bcb286d52f1a90fca52df0f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 21:33:18 2018 -0700
+
+    Add hb_array<>() specialization for UnsizedArrayOf
+
+    Related https://github.com/harfbuzz/harfbuzz/issues/1301
+
+ src/hb-aat-layout-trak-table.hh | 2 +-
+ src/hb-open-file.hh             | 2 +-
+ src/hb-open-type.hh             | 8 ++++++++
+ src/hb-ot-color-cpal-table.hh   | 6 +++---
+ 4 files changed, 13 insertions(+), 5 deletions(-)
+
+commit abfbba191141c3e3cf2a391f365b5323f9dc37c0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 21:27:45 2018 -0700
+
+    Add hb_array<>()
+
+    Simplifies transient object creation.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1301
+
+ src/hb-aat-layout-trak-table.hh | 2 +-
+ src/hb-dsalgs.hh                | 2 ++
+ src/hb-open-file.hh             | 3 +--
+ src/hb-ot-color-cpal-table.hh   | 6 +++---
+ 4 files changed, 7 insertions(+), 6 deletions(-)
+
+commit 17ffbc070ff4190d8ebaf88f8db62f19e6fa370d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 21:22:25 2018 -0700
+
+    [color] Use Index for colorIdx
+
+    Doesn't matter, but matches the description.
+
+ src/hb-ot-color-colr-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 07386ea410af13e8fc844eb939a6c6e47c2adaf1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 21:18:27 2018 -0700
+
+    Remove const and references when binding Null()
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1299
+
+    Removes anomaly I was seeing in cpal table trying to use implicit
+    Null(NameID).
+
+ src/hb-atomic.hh              | 5 +----
+ src/hb-common.cc              | 2 +-
+ src/hb-ft.cc                  | 2 +-
+ src/hb-null.hh                | 4 ++--
+ src/hb-open-type.hh           | 6 ++----
+ src/hb-ot-color-cpal-table.hh | 8 ++------
+ src/hb-static.cc              | 1 -
+ src/hb.hh                     | 9 +++++++++
+ 8 files changed, 18 insertions(+), 19 deletions(-)
+
+commit b18acab7bce062fef397d3d8b0efc7826f473b50
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 18:20:57 2018 -0700
+
+    [color] Add HB_COLOR
+
+    Normally I would have added to_string / from_string like other types
+    have.  But since we don't use hb_color_t much, I'm not going to
+    do that.
+    Although, if we did, we could use it in hb-view to parse colors...
+
+ src/hb-common.h | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+commit 228f96c9d09272c8f677935a640e75e173b817a3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 16:55:12 2018 -0700
+
+    [color] Finish reviewing / revamping CPAL
+
+    Now to hb_color_t.
+
+ src/hb-ot-color-cpal-table.hh | 52
+ ++++++++++++++++++++++---------------------
+ src/hb-ot-color.cc            | 33 +++++----------------------
+ src/hb-ot-color.h             | 10 ++++-----
+ 3 files changed, 38 insertions(+), 57 deletions(-)
+
+commit 960267fc4315a138f0963e78407e3af2ec6007af
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 16:37:39 2018 -0700
+
+    fix build attempt ^4
+
+ src/hb-ot-cff-common.hh | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+commit 683fad062792a199e2fe86fe161f41b9389d08c3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 16:35:03 2018 -0700
+
+    [color] Minor
+
+ src/hb-ot-color.cc | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 14474d21040bf9b025b53bb9b0df599eaf260119
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 16:30:30 2018 -0700
+
+    [color] Rely on CPALV1Tail Null object
+
+ src/hb-ot-color-cpal-table.hh | 39
+ ++++++++++++++-------------------------
+ 1 file changed, 14 insertions(+), 25 deletions(-)
+
+commit d7865107ea4664e04c03a1d79678cdcadc0d5ea5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 16:18:34 2018 -0700
+
+    Remove const from hb_array_t details
+
+    Will come in through <T> if desired.
+
+ src/hb-aat-layout-trak-table.hh | 6 +++---
+ src/hb-dsalgs.hh                | 6 +++---
+ src/hb-open-file.hh             | 4 ++--
+ 3 files changed, 8 insertions(+), 8 deletions(-)
+
+commit f3336580dd0c6959a1871f92b4a37f7c0a4b2160
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 16:16:21 2018 -0700
+
+    [color] Use hb_array_t in CPAL
+
+    Doesn't work though, ouch :(.  Need to figure out if it's unreasonable
+    to expect Null(T) inside hb_array_t<T> to see the later specialization
+    of Null for NameID.
+
+ src/hb-open-type.hh           |  3 ++-
+ src/hb-ot-color-cpal-table.hh | 47
+ ++++++++++++++++++++++---------------------
+ src/hb-static.cc              |  1 +
+ 3 files changed, 27 insertions(+), 24 deletions(-)
+
+commit 5ae18855d115577ff796158d483db7b890d9956f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 14:54:55 2018 -0700
+
+    [color] Check for null CPAL arrays
+
+    We cannot use a nullable offset here though.
+
+ src/hb-ot-color-cpal-table.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 69ab72e4aa7cbf197873d38f7e623866b4e40502
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 14:51:40 2018 -0700
+
+    [color] More CPAL rename
+
+ src/hb-ot-color-cpal-table.hh | 104
+ +++++++++++++++++++++---------------------
+ src/hb-ot-color.cc            |   6 +--
+ 2 files changed, 54 insertions(+), 56 deletions(-)
+
+commit 0befb06c468aa36f3337b5ef2235f6d69dda8397
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 14:46:21 2018 -0700
+
+    [color] More CPAL rename
+
+ src/hb-ot-color-cpal-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 3600d206037ef23d6448c79a3f010c4f903a971c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 14:43:12 2018 -0700
+
+    [color] Rename vars in CPAL
+
+ src/hb-ot-color-cpal-table.hh | 32 ++++++++++++++++----------------
+ src/hb-ot-color.cc            |  1 +
+ 2 files changed, 17 insertions(+), 16 deletions(-)
+
+commit ba055a8d53595ab49747ed3e02d90c9b6a3cf4f3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 16:20:04 2018 -0700
+
+    fix build attempt ^3
+
+ test/api/test-ot-extents-cff.c | 2 +-
+ test/api/test-subset-cff1.c    | 1 +
+ test/api/test-subset-cff2.c    | 1 +
+ 3 files changed, 3 insertions(+), 1 deletion(-)
+
+commit b11032afaefb2c84f9a4bbffe95c91f6374df802
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 15:52:37 2018 -0700
+
+    fix build attempt ^2
+
+ src/hb-ot-cff-common.hh        | 2 +-
+ test/api/test-ot-extents-cff.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 3d3df5575c5be0e3c69b99ca1d8df2cea1672aaf
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 15:23:39 2018 -0700
+
+    fix build attempt
+
+ src/hb-ot-cff-common.hh        |  5 ++++-
+ test/api/test-ot-extents-cff.c | 11 +++++------
+ test/api/test-subset-cff1.c    | 19 +++++++++----------
+ test/api/test-subset-cff2.c    | 11 +++++------
+ 4 files changed, 23 insertions(+), 23 deletions(-)
+
+commit 0babf761c986855f9cdd1a2679380ee6a02390c8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 23 01:33:45 2018 +0330
+
+    Adopt dump-emoji with latest unreleased APIs changes (#1297)
+
+ src/dump-emoji.cc | 24 +++++++++++-------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+commit 7997144b5f08c81b2cce2c7c2a085fb7eeb506e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 13:02:04 2018 -0700
+
+    [color] Revamp palette API
+
+ src/hb-ot-color.cc       |  81 ++++++++++++++---------------
+ src/hb-ot-color.h        |  26 +++++-----
+ test/api/test-ot-color.c | 130
+ +++++++++++++++++++++++------------------------
+ 3 files changed, 117 insertions(+), 120 deletions(-)
+
+commit 3bf91bd2690cda34a7687ed5465dc4bb0672f2b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 12:40:38 2018 -0700
+
+    [color] Rewrite colr access
+
+    COLR table has one function: return layers for a glyph, and we
+    expose exactly
+    that, so should just wire it through.  Also use sub_array() for
+    verifiable
+    safety.
+
+    Also, BaseGlyphRecord's null object is enough.  We don't need to
+    special-case
+    the not-found.
+
+ src/hb-dsalgs.hh              | 11 +++++++++
+ src/hb-open-type.hh           |  2 +-
+ src/hb-ot-color-colr-table.hh | 53
+ +++++++++++++++++++++++--------------------
+ src/hb-ot-color.cc            | 19 +---------------
+ 4 files changed, 41 insertions(+), 44 deletions(-)
+
+commit 1de17bdb80b0668f4d4a4700e3f80c8caee3303d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 22 10:29:01 2018 -0700
+
+    [colr] Add hb_ot_color_layer_t
+
+    We never return parallel arrays from functions.  That's inconvenient
+    and hard to bind.
+
+ src/hb-ot-color.cc       | 18 ++++++++----------
+ src/hb-ot-color.h        | 22 ++++++++++++++++------
+ test/api/test-ot-color.c | 33 +++++++++++++++------------------
+ 3 files changed, 39 insertions(+), 34 deletions(-)
+
+commit 3b3668acc8b16afacb96d8c525eff603ef5f411f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 19:23:11 2018 -0700
+
+    [color] Rename / reorder a bit
+
+    Implement has_data() for realz.
+
+ src/hb-ot-color-colr-table.hh |  2 ++
+ src/hb-ot-color-cpal-table.hh |  2 ++
+ src/hb-ot-color.cc            | 78
+ ++++++++++++++++++++++++-------------------
+ src/hb-ot-color.h             | 33 ++++++++++++------
+ test/api/test-ot-color.c      | 30 ++++++++---------
+ 5 files changed, 85 insertions(+), 60 deletions(-)
+
+commit 570b77f7d2b41262ccb20fadbee2c6b455cd06c6
+Merge: 857c5827 d440c8d3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 13:06:47 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 9085a72deb041cf10edfa61d24b7c25f947f736b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 19:08:25 2018 -0700
+
+    [cpal] Touch up palette flags
+
+ src/hb-ot-color.h        | 16 ++++++++++------
+ test/api/test-ot-color.c |  4 ++--
+ 2 files changed, 12 insertions(+), 8 deletions(-)
+
+commit ee11fae9d0d2c16a3a4b4ecf5cf328ffe950bb03
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 19:02:47 2018 -0700
+
+    [color] Rename "gid" to "glyph"
+
+    We don't expose "gid" in API.
+
+ src/hb-ot-color.cc | 12 ++++++------
+ src/hb-ot-color.h  |  8 ++++----
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit 228fa71bf9186faedff48b3a259d696c7c07b5b5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 17:43:29 2018 -0700
+
+    [colr] Move sanitize
+
+ src/hb-ot-color-colr-table.hh | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+commit d440c8d3fbb907f17b1eb9287918009ced27a8c1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 22 22:07:59 2018 +0330
+
+    Add chromacheck Emoji test fonts and minor preparations (#1294)
+
+ src/hb-ot-color.cc                  |  26 ++++++++++++++++++++++++++
+ src/hb-ot-face.hh                   |   8 +++++---
+ test/api/fonts/README               |   2 ++
+ test/api/fonts/chromacheck-cbdt.ttf | Bin 0 -> 792 bytes
+ test/api/fonts/chromacheck-colr.ttf | Bin 0 -> 652 bytes
+ test/api/fonts/chromacheck-sbix.ttf | Bin 0 -> 864 bytes
+ test/api/fonts/chromacheck-svg.ttf  | Bin 0 -> 792 bytes
+ test/api/hb-test.h                  |   2 +-
+ test/api/test-ot-color.c            |  21 +++++++++++++++++++++
+ 9 files changed, 55 insertions(+), 4 deletions(-)
+
+commit 857c58279e82897ed69e8ade2f736073fa12883b
+Merge: 51fba41c b92b9d7e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 22 09:57:20 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit b92b9d7e5290eaa83e94fd40cddaee71628a3c2a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 17:42:51 2018 -0700
+
+    [colr] Move compare function into a static
+
+    Not sure if MSVC would be unhappy about this.
+
+ src/hb-ot-color-colr-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit b6b171732a12b396a704984699bd0da906f5dc24
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 17:41:49 2018 -0700
+
+    [colr] Minor
+
+ src/hb-ot-color-colr-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit a6ade3471e730d7a8b56e4ed706a8eb126e957f6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 17:39:39 2018 -0700
+
+    [colr] Move sanitize() to right place
+
+    Sanitize always comes just before data member definitions, so
+    it's easy to cross-check.
+
+ src/hb-ot-color-colr-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 24adc1575745a711558dab79488760f1ceb24750
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 21 17:39:00 2018 -0700
+
+    [colr] Touch up a bit
+
+    When a struct is plain old data with no references, etc, it's okay
+    to mark its members public.
+
+ src/hb-ot-color-colr-table.hh | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+commit cc6e77ca98e90fb531dd90a5c9c41d14d1dda9c4
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sun Oct 21 13:29:40 2018 +0200
+
+    [color] Fix documentation a bit
+
+ src/hb-ot-color.cc | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 37ba2413c19f6a1d62868178fc80f870ee44e7ab
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 11:46:51 2018 +0330
+
+    Minor
+
+ src/hb-ot-color-cpal-table.hh | 10 +++++-----
+ src/hb-ot-color.cc            | 25 ++++++++++++++-----------
+ src/hb-ot-color.h             | 12 ++++++------
+ 3 files changed, 25 insertions(+), 22 deletions(-)
+
+commit 44f79b4bf8ac341c5968a27f6a2a13a8af48b34f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 10:17:34 2018 +0330
+
+    Remove _palette_entry_count as can be done with _palette_colors
+
+ src/hb-ot-color.cc       | 18 ++----------------
+ src/hb-ot-color.h        |  3 ---
+ test/api/test-ot-color.c |  8 ++------
+ 3 files changed, 4 insertions(+), 25 deletions(-)
+
+commit 6795dcfc0884b87b72fce8d902654f28ffe1366c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 09:51:15 2018 +0330
+
+    [test] Test hb_ot_color_has_{colr,cpal}_data
+
+ src/dump-emoji.cc        |  3 ++-
+ src/hb-ot-color.cc       |  7 ++++---
+ test/api/test-ot-color.c | 23 +++++++++++++++++++++++
+ 3 files changed, 29 insertions(+), 4 deletions(-)
+
+commit b8ee3a0ec89d63721618ac90c01ac6da228f5055
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 09:44:16 2018 +0330
+
+    [CPAL] Add palette entry and enable palette flag API
+
+ src/hb-ot-color-cpal-table.hh |  66 +++++++++++++++----------
+ src/hb-ot-color.cc            | 109
+ ++++++++++++++++++++++++------------------
+ src/hb-ot-color.h             |  23 +++++++++
+ test/api/test-ot-color.c      |  35 ++++++++++++--
+ 4 files changed, 158 insertions(+), 75 deletions(-)
+
+commit d4261b4bb6d20fac7deebacfbe120fb84a92e423
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 08:48:07 2018 +0330
+
+    Add API test for hb_ot_color_get_color_layers
+
+ src/dump-emoji.cc        |  3 ++-
+ src/hb-ot-color.cc       |  2 +-
+ src/hb-ot-color.h        |  2 ++
+ test/api/test-ot-color.c | 31 +++++++++++++++++++++++++++++--
+ 4 files changed, 34 insertions(+), 4 deletions(-)
+
+commit 456978d408cd41156e1123abfc3689800558e89b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 08:26:40 2018 +0330
+
+    Address COLR/CPAL reviews and revive cpal_v1 tests
+
+ src/dump-emoji.cc             |  26 ++++----
+ src/hb-common.h               |  12 ++++
+ src/hb-ot-color-cpal-table.hh |  37 +++++-------
+ src/hb-ot-color.cc            | 136
+ +++++++++++++++++++++++++-----------------
+ src/hb-ot-color.h             |  38 +++---------
+ test/api/test-ot-color.c      | 101 +++++++++++++++----------------
+ 6 files changed, 179 insertions(+), 171 deletions(-)
+
+commit 687f679b80c071c69d0924f07a315f9d2691b7fc
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 17:50:39 2018 +0330
+
+    [color] Fix alpha channel value and adjust spaces
+
+ src/dump-emoji.cc          | 36 ++++++++++++++++++------------------
+ src/hb-buffer-serialize.cc | 14 +++++++-------
+ src/hb-ot-color.cc         | 10 +++++-----
+ 3 files changed, 30 insertions(+), 30 deletions(-)
+
+commit 00e94ce24efb1f5b3a9cd13c0b9f81f405ad8055
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 00:31:04 2018 +0330
+
+    [dump-emoji] Formatting
+
+ src/dump-emoji.cc | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+commit e9d798dc12d42e97ae8c19e7b73e25abc34d265a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 18:30:01 2018 +0330
+
+    [test] Use hb_test_open_font_file
+
+ test/api/test-ot-color.c | 16 ++--------------
+ 1 file changed, 2 insertions(+), 14 deletions(-)
+
+commit e8a6f5b8039cce3f7ec568fd90fe73690e49a037
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 18:23:42 2018 +0330
+
+    Add three macros for separating color channels
+
+ src/dump-emoji.cc        |  8 ++++----
+ src/hb-ot-color.cc       |  1 -
+ src/hb-ot-color.h        | 15 ++++++++++-----
+ test/api/test-ot-color.c | 10 +++++-----
+ 4 files changed, 19 insertions(+), 15 deletions(-)
+
+commit 0e33467e52942e62e04cf825a6bd105fa311c864
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 17:44:06 2018 +0330
+
+    Make ot-color tests pass
+
+ test/api/test-ot-color.c | 52
+ ++++++++++++++++++++++++------------------------
+ 1 file changed, 26 insertions(+), 26 deletions(-)
+
+commit d4e928b1421c154adbda9b6e1f2cf804b21654cb
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Tue May 1 17:16:46 2018 +0200
+
+    [color] Minimal API for COLR/CPAL
+
+ src/Makefile.sources                               |   1 +
+ src/dump-emoji.cc                                  | 114
+ +++++++++++----------
+ src/hb-ot-color-colr-table.hh                      |  12 +--
+ src/hb-ot-color-cpal-table.hh                      |  51 +++------
+ src/hb-ot-color.cc                                 |  87 +++++++++++-----
+ src/hb-ot-color.h                                  |  85 +++++++++++++++
+ src/hb-ot-face.hh                                  |   3 +
+ src/hb-ot.h                                        |   1 +
+ .../fonts/cpal-v0.ttf}                             | Bin
+ .../fonts/cpal-v1.ttf}                             | Bin
+ test/api/test-ot-color.c                           |  43 +++++---
+ 11 files changed, 257 insertions(+), 140 deletions(-)
+
+commit 0229eaea299443b4faa3bd086f23ec1496d6112c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 22 10:51:37 2018 +0330
+
+    [fuzz] Add a found hb-subset testcase
+
+ ...z-testcase-minimized-hb-subset-fuzzer-5725847365877760 | Bin 0 ->
+ 880 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 0ecddad7c5948ecd7879bc7507f8a7a2d99eee86
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 22 00:44:28 2018 +0330
+
+    [ci] Disable flaky -windows-x64 and add a comment for iOS
+
+ .circleci/config.yml | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+commit 9b3461574f6473c8ff7c995202858cf46012eed8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 11:37:38 2018 +0330
+
+    [fuzz] Add more testcases
+
+    Fixed already but better to have anyway.
+
+    One didn't have minimized but it was only 164 B, so
+
+ ...uzz-testcase-minimized-hb-shape-fuzzer-5706010589659136 | Bin 0 ->
+ 52 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 4fa94a3e39c21bc1dcdbbd5bda99bff1e1490b0e
+Merge: 217a3728 c110878c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 11:36:41 2018 +0330
+
+    Merge pull request #1290 from ebraminio/testopenfont
+
+    [test] Unify font file opening across the tests
+
+commit c110878cb61f5df99e9d97dda253f2987ddce58e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Oct 21 11:07:17 2018 +0330
+
+    [test] Unify font file opening across the tests
+
+ test/api/hb-subset-test.h        | 21 ---------------------
+ test/api/hb-test.h               | 21 +++++++++++++++++++++
+ test/api/test-collect-unicodes.c |  6 +++---
+ test/api/test-multithread.c      | 26 +++++---------------------
+ test/api/test-ot-name.c          | 27 ++++-----------------------
+ test/api/test-subset-cmap.c      |  8 ++++----
+ test/api/test-subset-glyf.c      | 28 ++++++++++++++--------------
+ test/api/test-subset-hdmx.c      | 14 +++++++-------
+ test/api/test-subset-hmtx.c      | 20 ++++++++++----------
+ test/api/test-subset-os2.c       |  4 ++--
+ test/api/test-subset-post.c      |  4 ++--
+ test/api/test-subset-vmtx.c      |  6 +++---
+ test/api/test-subset.c           |  6 +++---
+ 13 files changed, 78 insertions(+), 113 deletions(-)
+
+commit 217a3728b4991a855070678bc079cb400eee605a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 20:39:56 2018 -0700
+
+    [fuzzing] Add more font
+
+ .../clusterfuzz-testcase-hb-shape-fuzzer-5097734906839040 | Bin 0 ->
+ 164 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 1e39833ba8547c90a0a4ed7f265a6c4bc8eb8fe1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 16:56:06 2018 -0700
+
+    [docs] Minor
+
+ src/hb-buffer.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit a5ad8c658dac1fbe63d1034cdfe8df33f50462b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 16:52:55 2018 -0700
+
+    [docs] More fixes
+
+ src/hb-ot-layout.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 2d9198f205fafda557520d7206f9cfbf3373353f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 16:50:39 2018 -0700
+
+    [docs] Fix for hb-version.h being in src tree
+
+ docs/Makefile.am | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 314b1af74f1fb71ea5cfcb5a58766773f0b2a5a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 16:49:16 2018 -0700
+
+    [docs] Fix warning
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1260
+
+ src/hb-deprecated.h | 6 ------
+ src/hb-unicode.cc   | 1 +
+ 2 files changed, 1 insertion(+), 6 deletions(-)
+
+commit b713c1397718bf1f702a2ead2afb4dcee2c1505a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 14:56:28 2018 -0700
+
+    [kerx] Implement tuple-kerning in Format0
+
+ src/hb-aat-layout-kerx-table.hh | 44
+ ++++++++++++++++++++++++++++-------------
+ 1 file changed, 30 insertions(+), 14 deletions(-)
+
+commit 0a3b7a0fb0734a66926dfda5d95d3cacea8890ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 13:14:07 2018 -0700
+
+    2.0.2
+
+ NEWS             | 6 ++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+commit 8931bc4a6b41a2a41069b99cb5c551fa30216f0b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 23:23:32 2018 +0330
+
+    [test] Fix -Wunused-parameter on test-font.c
+
+ test/api/test-font.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 68b705076808d4b0a4ac3bfa945b8f9ae23db1df
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 12:09:41 2018 -0700
+
+    [kerx] Fix sanitize of KerxSubtableFormat2::array read
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11033
+
+ src/hb-aat-layout-kerx-table.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 00fdbca4f6a5c4623b9c4838da502cccce8aaa74
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 12:04:51 2018 -0700
+
+    [aat] Fix LookupFormat10 sanitize
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11060
+
+ src/hb-aat-layout-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f11c557662dee16a59bb54276c50a96e4e675201
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 20 11:56:30 2018 -0700
+
+    [test] Fix leak
+
+ test/api/test-font.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 440a675c7cc72c7c77b4ad7b20c855c53808ef48
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 21:13:25 2018 +0330
+
+    [TODO] Remove BCP 47 language handling item
+
+    Closes https://github.com/harfbuzz/harfbuzz/issues/1286
+
+ TODO | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit d39acc5a95f968b0dbfd5a942abda606d9aa3343
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 12:20:30 2018 +0330
+
+    [fuzzing] Add new testcases
+
+ .../clusterfuzz-testcase-hb-shape-fuzzer-5688420752424960 | Bin 0 ->
+ 163 bytes
+ ...zz-testcase-minimized-hb-shape-fuzzer-5688420752424960 | Bin 0 ->
+ 69 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 1e55e21dea78aaaddc0715e7df96fd198ec8f78a
+Merge: 964ae32a d084719f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 07:45:46 2018 +0330
+
+    Merge pull request #1283 from khaledhosny/cygwin
+
+    Cygwin fixes and CI build
+
+commit 964ae32aac793540a49c44efab878592394d48db
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 20 07:39:18 2018 +0330
+
+    Run valgrind on run-shape-fuzzer only when RUN_VALGRIND is set (#1285)
+
+ .circleci/config.yml                   | 2 +-
+ test/fuzzing/run-shape-fuzzer-tests.py | 4 +++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+commit f70f994112b2577271c20a929f7b980fa1d17428
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 20:00:36 2018 -0700
+
+    Minor
+
+ test/api/test-ot-name.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4e09fb8f7a93ec0c8d7f71cd58772ba468b5523f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 19:59:41 2018 -0700
+
+    Oops. Fix build
+
+ test/api/test-map.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9e288d29d86ef27acacd397b1abf04d512f1e61e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 19:47:27 2018 -0700
+
+    [test-map] Cosmetic
+
+ test/api/test-map.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+commit 7c2c8ac301b526da8b5384d6b90f156ca096568e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 19:37:46 2018 -0700
+
+    2.0.1
+
+ NEWS             | 15 ++++++++++++++-
+ configure.ac     |  2 +-
+ src/hb-version.h |  4 ++--
+ 3 files changed, 17 insertions(+), 4 deletions(-)
+
+commit 5a24ea15e0c242c3e2a4a49980da3ab7dd61a3df
+Author: Bruce Mitchener <bruce.mitchener@gmail.com>
+Date:   Sat Oct 20 08:09:52 2018 +0700
+
+    Make more 'coords' params const.
+
+ src/hb-ot-layout-common.hh   | 8 ++++----
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ src/hb-ot-var-hvar-table.hh  | 2 +-
+ src/hb-ot-var-mvar-table.hh  | 2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 08b7172969b442cc83b47f44e685a0495b2d8cd4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 19:12:33 2018 -0700
+
+    [font] Fix parallel funcs passing to eachover in infinite-loop
+
+    Fixes test just added.
+
+ src/hb-font.cc | 20 +++++++++++++-------
+ src/hb-font.hh |  8 ++++++++
+ 2 files changed, 21 insertions(+), 7 deletions(-)
+
+commit 77d5c3df07bec8e9d2dd57f89d5810b768bdc4f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 19:01:01 2018 -0700
+
+    [font] Add failing test amongst font-func parallels infinite-looping
+
+    Reported by Nona while updating Android to HarfBuzz 2.0.0.
+
+ test/api/test-font.c | 64
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+commit d084719ff5a9e0e363bf352037f85b884bff11a7
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Oct 20 00:18:36 2018 +0200
+
+    Add Cygwin CI build
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1274
+
+ appveyor.yml | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+commit 29d877518fc2c29083cd7b955b422087966235f7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 16:06:54 2018 -0700
+
+    [kerx] Implement variation-kerning tables (without the variation part)
+
+    SFSNDisplay uses these.  We just apply the default kern without
+    variations right now.  But at least makes the default kern work.
+
+ src/hb-aat-layout-kerx-table.hh | 37
+ +++++++++++++++++++++++++++++--------
+ 1 file changed, 29 insertions(+), 8 deletions(-)
+
+commit f7c0b4319c6f82f1e0020a0029469d8953a7a161
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 15:23:49 2018 -0700
+
+    [aat] Implement LookupFormat10
+
+ src/hb-aat-layout-ankr-table.hh |  6 +++--
+ src/hb-aat-layout-common.hh     | 55
+ ++++++++++++++++++++++++++++++++++++++---
+ src/hb-machinery.hh             |  4 +++
+ src/hb-open-type.hh             |  3 +++
+ 4 files changed, 63 insertions(+), 5 deletions(-)
+
+commit cf92cb7e002f479505fed8c2c55ab12dcbea2d83
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Fri Oct 19 22:21:39 2018 +0200
+
+    Use g_strdup instead of strdup
+
+    Cygwin does not seem to have strdup.
+
+ util/options.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 30cbe6158de1ddc0546d55e4edc1fe264e1b86ef
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Fri Oct 19 22:04:56 2018 +0200
+
+    Use O_BINARY instead of _O_BINARY
+
+    Cygwin does not seem to have the later
+
+ src/hb-blob.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 257ded1f9ec653d15e79d2ea0a83bd8c5c53d831
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 11:20:14 2018 -0700
+
+    [trak] Fix test for previous fix
+
+ test/shaping/data/in-house/tests/aat-trak.tests | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 72bb139b807c21f1569058fb5fb260dcdd81eba4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 11:15:35 2018 -0700
+
+    [RELEASING] Post-mortem
+
+    Re https://github.com/harfbuzz/harfbuzz/issues/1271
+
+ RELEASING.md | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 79b63561552bdfe8dc67a450d740fda8802486ad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 11:00:20 2018 -0700
+
+    [trak] Fix extrapolation at end side
+
+ src/hb-aat-layout-trak-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2352cc3539b2e58d0481cdb8b9cd48cbc09a778e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 19 09:58:45 2018 -0700
+
+    [kerx] Whitespace
+
+ src/hb-aat-layout-kerx-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 114f66dda6a07d61b5e64da5c44b05db7aa51cc9
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 12:05:26 2018 +0330
+
+    Fix hb_map_is_empty logic
+
+    This needs reviewing
+
+ src/hb-map.hh       |  2 +-
+ test/api/test-map.c | 13 ++++++++-----
+ 2 files changed, 9 insertions(+), 6 deletions(-)
+
+commit 9df2fb1611e03e401f0d5a9432b440641085ba1e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 12:04:47 2018 +0330
+
+    Add API tests for hb_map_t
+
+ src/Makefile.am      |   2 +-
+ test/api/Makefile.am |   6 ++-
+ test/api/test-map.c  | 114
+ +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 120 insertions(+), 2 deletions(-)
+
+commit 8a5eba711069285e8d8b6d682eea0090256527bb
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 10:20:16 2018 +0330
+
+    [test] cosmetic, use g_assert_cmpint
+
+ test/api/test-ot-name.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit c6eb5e852c24e12fec3138cf9def5eb76acedfd6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 10:14:25 2018 +0330
+
+    Don't report deprecated symbols as unused symbols
+
+ src/Makefile.am      | 2 ++
+ test/api/Makefile.am | 4 +++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit 34f357c78a7a530fdb3580ec9d3d865600c06128
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 10:13:53 2018 +0330
+
+    Add test for hb_set_del
+
+ test/api/test-set.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 4594730f64e534e975065afce925b581fd9c6acd
+Author: Bruce Mitchener <bruce.mitchener@gmail.com>
+Date:   Fri Oct 19 22:12:25 2018 +0700
+
+    Remove redundant return at end of void-returning function.
+
+ src/hb-ot-layout-gsubgpos.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 093c7c4a54b37f5b12ad21e2d67f109597d068b1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 18:46:41 2018 +0330
+
+    [ci] Run valgrind on test/api
+
+    run-shape-fuzzer-tests.py automatically runs valgrind if see available
+    but test/api runs it by request, we probably should normalize the
+    approaches
+    later
+
+ .circleci/config.yml | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 8d1e479d1dcf7789be99a6cd0db0b883a90299dc
+Author: Bruce Mitchener <bruce.mitchener@gmail.com>
+Date:   Thu Oct 18 22:18:42 2018 +0700
+
+    Use bool literals instead of 0/1.
+
+ src/hb-common.cc               | 2 +-
+ src/hb-coretext.cc             | 4 ++--
+ src/hb-ot-layout-gpos-table.hh | 2 +-
+ src/hb-ot-tag.cc               | 2 +-
+ src/hb-shape-plan.cc           | 8 ++++----
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+commit 257d0e5aa36fd5b3e54e04918ce12bb7d7e0d177
+Author: Bruce Mitchener <bruce.mitchener@gmail.com>
+Date:   Fri Oct 19 22:49:21 2018 +0700
+
+    Fix typos.
+
+ BUILD.md                       | 2 +-
+ CMakeLists.txt                 | 8 ++++----
+ README.python.md               | 2 +-
+ README.wine.md                 | 6 +++---
+ src/hb-machinery.hh            | 2 +-
+ src/hb-null.hh                 | 4 ++--
+ src/hb-open-file.hh            | 2 +-
+ src/hb-ot-layout-common.hh     | 2 +-
+ src/hb-ot-layout-gdef-table.hh | 2 +-
+ src/hb-ot-layout-gsub-table.hh | 2 +-
+ src/hb-ot-layout-gsubgpos.hh   | 2 +-
+ 11 files changed, 17 insertions(+), 17 deletions(-)
+
+commit b7cef8cb1dfaf1f0f2c0d79b96b171049b69466a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 09:24:21 2018 +0330
+
+    Enable valgrind and dedicate a bot to it
+
+ .circleci/config.yml                   | 13 +++++++++++++
+ test/fuzzing/run-shape-fuzzer-tests.py | 31
+ +++++++++++++++++++++++++++++++
+ 2 files changed, 44 insertions(+)
+
+commit bccd09d6c7baa99fdaccb8c5b3ff7e1834edd3bf
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 09:06:42 2018 +0330
+
+    Minor, tweak spaces on hb-shape-fuzzer.cc
+
+ test/fuzzing/hb-shape-fuzzer.cc | 42
+ ++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+commit fbf665b307c8cc9f16f5897671bfdd8719a195b5
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 19 08:09:53 2018 +0330
+
+    [fuzz] Add more found cases (#1275)
+
+ ...clusterfuzz-testcase-hb-shape-fuzzer-5728971283496960 | Bin 0 ->
+ 101 bytes
+ ...terfuzz-testcase-minimized-hb-fuzzer-5713868010553344 | Bin 0 ->
+ 370 bytes
+ ...terfuzz-testcase-minimized-hb-fuzzer-6278851874258944 | Bin 0 ->
+ 598 bytes
+ ...z-testcase-minimized-hb-shape-fuzzer-5649959857160192 | Bin 0 ->
+ 3608 bytes
+ ...z-testcase-minimized-hb-shape-fuzzer-5664873493561344 | Bin 0 ->
+ 400 bytes
+ ...z-testcase-minimized-hb-shape-fuzzer-5762953198960640 | Bin 0 ->
+ 62 bytes
+ ...z-testcase-minimized-hb-shape-fuzzer-5764636557705216 | Bin 0 ->
+ 2184 bytes
+ ...-testcase-minimized-hb-subset-fuzzer-5690658895953920 | Bin 0 ->
+ 2735 bytes
+ ...-testcase-minimized-hb-subset-fuzzer-5695279609675776 | Bin 0 ->
+ 135 bytes
+ ...-testcase-minimized-hb-subset-fuzzer-5718215406125056 | Bin 0 ->
+ 107 bytes
+ ...-testcase-minimized-hb-subset-fuzzer-5743250149736448 | Bin 0 ->
+ 103 bytes
+ ...-testcase-minimized-hb-subset-fuzzer-5765071062958080 | Bin 0 ->
+ 329 bytes
+ ...ized-hb-subset-get-codepoints-fuzzer-5930139383758848 | Bin 0 ->
+ 9410 bytes
+ 13 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 51fba41cc958ded3afc6c1e738895b0a81993e18
+Merge: e555ed96 3d9a0306
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 18 13:08:42 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit e555ed961e86104e059861efe4245b7b146dbd3b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 18 13:04:41 2018 -0700
+
+    added flex extents test
+
+ test/api/fonts/cff1_flex.otf   | Bin 0 -> 3152 bytes
+ test/api/test-ot-extents-cff.c |  23 +++++++++++++++++++++++
+ 2 files changed, 23 insertions(+)
+
+commit 8679d02b4b3f2f9147c4ea0319eb39851c4e40e6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 18 13:04:21 2018 -0700
+
+    implement flex ops for glyph extents/subset
+
+    also removed unused CSInterpEnv::move_[xy]_with_arg
+    fixed bug a width being left over on argStack with CFF1
+
+ src/hb-cff-interp-cs-common.hh | 157
+ +++++++++++++++++++++++++++++++++++------
+ src/hb-cff1-interp-cs.hh       |   1 +
+ src/hb-subset-cff1.cc          |   4 --
+ src/hb-subset-cff2.cc          |   4 --
+ 4 files changed, 138 insertions(+), 28 deletions(-)
+
+commit 3d9a0306ebb48706778fd2c487c3cacc7d508d6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 18 05:58:17 2018 -0700
+
+    2.0.0
+
+ NEWS                | 68
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ configure.ac        |  2 +-
+ src/hb-buffer.cc    |  4 ++--
+ src/hb-common.h     |  4 ++--
+ src/hb-deprecated.h | 18 +++++++-------
+ src/hb-font.cc      |  6 ++---
+ src/hb-font.h       |  2 +-
+ src/hb-ot-layout.cc |  8 +++----
+ src/hb-ot-name.h    |  4 ++--
+ src/hb-ot-tag.cc    |  4 ++--
+ src/hb-ot-tag.h     |  4 ++--
+ src/hb-version.h    |  6 ++---
+ 12 files changed, 99 insertions(+), 31 deletions(-)
+
+commit 535ca678bf9c8ab470ebf5ad84a090328d79d42b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 18 05:58:04 2018 -0700
+
+    [test] Don't use newer glib API
+
+ test/api/test-ot-tag.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 03e144135b5c691e3942d1aef917fe2246665fb6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 11:06:37 2018 +0330
+
+    [ubsan] Use unsigned int instead enum where needed (#1270)
+
+    Actually the check is right,
+
+    On -myanmar.hh, on that particular switch, OT_C is indic_category_t
+    but OT_D is myanmar_category_t so we are mixing the types in one
+    variable.
+
+    And on -arabic.cc, step can goes one number higher than step_t enum
+    in the
+    loop so we are actually using it as an unsinged int.
+
+ .circleci/config.yml               |  2 +-
+ src/hb-ot-shape-complex-arabic.cc  |  4 ++--
+ src/hb-ot-shape-complex-myanmar.hh | 48
+ +++++++++++++++++++-------------------
+ 3 files changed, 27 insertions(+), 27 deletions(-)
+
+commit 64df6b0b0f9d221e14811084f2412a01cf4deb46
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 18 00:35:01 2018 -0700
+
+    [AUTHORS] Add Ebrahim and Khaled
+
+ AUTHORS | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+commit f1ced9be378d7c7ad3ea35a1cee6f9aff7a44a13
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 23:06:53 2018 -0700
+
+    More warning fix
+
+    Okay, let's see if the gods are happy now...
+
+ src/hb-static.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 40606abd0cd40faf3973d0a8c30af90d36ae8231
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 23:06:37 2018 -0700
+
+    Fix build
+
+ src/hb-static.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c406aca19303e61fa5ba15d215386cfc6d920124
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 22:58:43 2018 -0700
+
+    Fix warning
+
+ src/hb-machinery.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 270a37c3244b32dd839a99eb379be241613ee895
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 22:42:47 2018 -0700
+
+    Kick bots
+
+ src/hb-aat-layout-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 6da8ef3f9f4706fe88715fabdba7904ff279539b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 22:37:34 2018 -0700
+
+    Fix some wierdness...
+
+ src/hb-static.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 83780308b41b029513ac2568b6688d3eaad77338
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 22:34:16 2018 -0700
+
+    [aat] Fix sanitize slowdown
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11034
+
+ src/hb-aat-layout-common.hh | 4 ++++
+ src/hb-machinery.hh         | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit b9478e28ac4361353e4920d749cc5d29e5bfef67
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 21:52:14 2018 -0700
+
+    Revert "[test] Remove not-fixed yet testcases (#1268)"
+
+    This reverts commit 191eef823fe95355425621f8e002dfe7fe632383.
+
+ ...rfuzz-testcase-minimized-hb-fuzzer-4548492505645056 | Bin 0 ->
+ 122 bytes
+ ...rfuzz-testcase-minimized-hb-fuzzer-6210176798425088 | Bin 0 ->
+ 1420 bytes
+ ...testcase-minimized-hb-shape-fuzzer-5738888765636608 | Bin 0 ->
+ 267731 bytes
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+
+commit af99b20dfddbca75e68f84c5aa465a54728990a6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 08:35:20 2018 +0330
+
+    [ci/ubsan] Disable enum sanitization
+
+    Behdad apparently not interested on them
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9e8a9b846ec24e9124d61706272a0e5fa58d7a24
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 21:41:25 2018 -0700
+
+    [aat] Another try at fixing Lookup null objects...
+
+    Ugly as hell, and don't even understand why some bits are needed.
+    But the logic is sound.
+
+ src/hb-aat-layout-common.hh | 23 ++++++++++++++++++++---
+ src/hb-static.cc            |  4 ++++
+ 2 files changed, 24 insertions(+), 3 deletions(-)
+
+commit 191eef823fe95355425621f8e002dfe7fe632383
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 08:04:18 2018 +0330
+
+    [test] Remove not-fixed yet testcases (#1268)
+
+    I added them but now that I think, it is a bad idea to have them as
+    fuzzing bots will find good seeds to tweak in order to find easy new
+    testcases which causes duplicated issues.
+
+ ...rfuzz-testcase-minimized-hb-fuzzer-4548492505645056 | Bin 122 ->
+ 0 bytes
+ ...rfuzz-testcase-minimized-hb-fuzzer-6210176798425088 | Bin 1420 ->
+ 0 bytes
+ ...testcase-minimized-hb-shape-fuzzer-5738888765636608 | Bin 267731 ->
+ 0 bytes
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 392e1f4ddd7eb649e1a71755b9bcf6431739f98f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 07:42:20 2018 +0330
+
+    [test/shape-fuzzer] fail on timeout and ubsan errors (#1267)
+
+ test/fuzzing/run-shape-fuzzer-tests.py | 38
+ ++++++++++++++++++++++++++++++----
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+commit eeddda3ec6c28b411d33c74938ec6198c7f6888d
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 07:38:47 2018 +0330
+
+    [util] Better file-not-found error from hb-shape / hb-view
+
+    fixes #1266
+
+ util/options.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 751c10e55e43e2266a5bba024d560c5127fae4b8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 06:36:48 2018 +0330
+
+    [fuzz] Add more new testcases
+
+ ...testcase-minimized-hb-shape-fuzzer-5718464350650368 | Bin 0 ->
+ 41 bytes
+ ...testcase-minimized-hb-shape-fuzzer-5738888765636608 | Bin 0 ->
+ 267731 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit fd282eb3285e6d20f77e8a3a7237b677433ccbb4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 18 06:33:39 2018 +0330
+
+    [fuzz] Add a new testcase
+
+ .../clusterfuzz-testcase-hb-shape-fuzzer-5634395566768128 | Bin 0 ->
+ 106 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 9d42d70269b879e67f3c7724beab8e4cdbfc877a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 17:55:47 2018 -0700
+
+    [trak] Fix calc
+
+    We were getting the first track record always.  Ie. this line:
+
+           if (trackTable[i].get_track_value () == 0.f)
+           {
+    -       trackTableEntry = &trackTable[0];
+    +       trackTableEntry = &trackTable[i];
+            break;
+           }
+
+    The rest is cleanup.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1263 for the
+    most part.
+
+ src/hb-aat-layout-trak-table.hh | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+commit 3341c7fbfb9bc8e137afd9f16da8cf18eb67b25b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 17 15:04:35 2018 -0700
+
+    [fuzzing] Move fuzzing fonts from api/ here
+
+ ...estcase-minimized-hb-subset-fuzzer-5521982557782016 | Bin 1228 ->
+ 0 bytes
+ ...estcase-minimized-hb-subset-fuzzer-5542653037903872 | Bin 160249 ->
+ 0 bytes
+ ...estcase-minimized-hb-subset-fuzzer-5609911946838016 | Bin 313 ->
+ 0 bytes
+ ...estcase-minimized-hb-subset-fuzzer-5670861909524480 | Bin 1298 ->
+ 0 bytes
+ ...estcase-minimized-hb-subset-fuzzer-5750092395970560 | Bin 72435 ->
+ 0 bytes
+ ...estcase-minimized-hb-subset-fuzzer-6651660668502016 | Bin 15229 ->
+ 0 bytes
+ ...ed-hb-subset-get-codepoints-fuzzer-5973295416475648 | Bin 109 ->
+ 0 bytes
+ ...ed-hb-subset-get-codepoints-fuzzer-6136125075750912 | Bin 65816 ->
+ 0 bytes
+ test/api/test-subset-glyf.c                            |   2 +-
+ test/api/test-subset-hdmx.c                            |   4 ++--
+ test/api/test-subset-hmtx.c                            |   2 +-
+ test/api/test-subset.c                                 |   6 +++---
+ .../crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249     | Bin
+ .../crash-b577db318b30f2851828a4c9ef97cb30678b1b54     | Bin
+ .../crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a     | Bin
+ .../crash-e4e0bb1458a91b692eba492c907ae1f94e635480     | Bin
+ .../fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653 | Bin
+ .../fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a | Bin
+ 18 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 1f34388e8b40a77157f61c8e1a2fc7c4846c192e
+Merge: 9ade3e7b 2e7c7165
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 17 09:34:48 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 2e7c716511e8b2cfcd059fa2a2ed4cdd48b351bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 18:35:03 2018 -0700
+
+    [buffer] Add an assert
+
+    See if it helps debugging
+    https://bugs.chromium.org/p/chromium/issues/detail?id=895117
+
+ src/hb-buffer.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 5842756b1398253d38749c4c8a23a1450e642caf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 18:28:55 2018 -0700
+
+    [fuzzing] Delete blink fuzzed data
+
+    These are text, not font.
+
+ ...minimized-blink_harfbuzz_shaper_fuzzer-5099655095123968 | Bin 88 ->
+ 0 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 25fe7e7e1031401d38db1efed360cd75ea7910b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 18:22:54 2018 -0700
+
+    [aat] Comment
+
+ src/hb-aat-layout-common.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 26092bb3d1aa239de5e933700e0371619d147f65
+Author: HinTak <htl10@users.sourceforge.net>
+Date:   Wed Oct 17 00:54:39 2018 +0100
+
+    "allow-none" annotation for "out" parameters
+
+    Fixes the following warnings:
+    hb-ot-tag.cc:330: Warning: HarfBuzz: invalid "allow-none" annotation:
+    only valid for pointer types and out parameters
+    hb-ot-tag.cc:334: Warning: HarfBuzz: invalid "allow-none" annotation:
+    only valid for pointer types and out parameters
+
+ src/hb-ot-tag.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit ba42651608da1be0d152e03ad42ea96fc8476ac7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 17:35:46 2018 -0700
+
+    Fix indent
+
+ test/fuzzing/run-shape-fuzzer-tests.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 49bdb54427b17d439eadf31732a5f2a0add46bf5
+Author: HinTak <htl10@users.sourceforge.net>
+Date:   Wed Oct 17 00:36:04 2018 +0100
+
+    typo in gobject annotation - "in/out" should be "inout"
+
+    "in/out" should be "inout"
+
+ src/hb-ot-layout.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c0c190c16a2c1b281f40dacdcf515dc5a59ab3bb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:39:29 2018 -0700
+
+    [fuzzing] Run tests against fuzzing fonts
+
+    Some disable.
+
+ test/fuzzing/run-shape-fuzzer-tests.py        | 12 ++--
+ test/fuzzing/run-subset-fuzzer-tests.py       | 35 ++++++-----
+ test/shaping/data/in-house/Makefile.sources   |  1 -
+ test/shaping/data/in-house/tests/fuzzed.tests | 84
+ ---------------------------
+ 4 files changed, 24 insertions(+), 108 deletions(-)
+
+commit 7b37705fb579a39334be0618c6215c1b887bf9fc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:33:06 2018 -0700
+
+    [fuzzing] Rename
+
+ ...ebdebc6.ttf => 0509e80afb379d16560e9e47bdd7d888bebdebc6} | Bin
+ ...63b6daf.ttf => 1a6f1687b7a221f9f2c834b0b360d3c8463b6daf} | Bin
+ ...28b22cb.ttf => 205edd09bd3d141cc9580f650109556cc28b22cb} | Bin
+ ...f026462.ttf => 217a934cfe15c548b572c203dceb2befdf026462} | Bin
+ ...ac34f18.ttf => 3511ff5c1647150595846ac414c595cccac34f18} | Bin
+ ...675d5a3.ttf => 375d6ae32a3cbe52fbf81a4e5777e3377675d5a3} | Bin
+ ...9c9a56b.ttf => 43979b90b2dd929723cf4fe1715990bcb9c9a56b} | Bin
+ ...1a8e2b0.ttf => 558661aa659912f4d30ecd27bd09835171a8e2b0} | Bin
+ ...0655fa8.ttf => 5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8} | Bin
+ ...c149ddc.ttf => 641bd9db850193064d17575053ae2bf8ec149ddc} | Bin
+ ...bcf861f.ttf => 8240789f6d12d4cfc4b5e8e6f246c3701bcf861f} | Bin
+ ...1386016.ttf => a34a9191d9376bda419836effeef7e75c1386016} | Bin
+ ...bdae30e.ttf => a69118c2c2ada48ff803d9149daa54c9ebdae30e} | Bin
+ ...6b31fe2.ttf => b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2} | Bin
+ ...14a0467.ttf => e88c339237f52d21e01c55f01b9c1b4cc14a0467} | Bin
+ ...1395725.ttf => fab39d60d758cb586db5a504f218442cd1395725} | Bin
+ 16 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 3676c685d407cc7b9b813b4a08e7c5bcd9a47ea1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:32:26 2018 -0700
+
+    [fuzzing] Move rest of fuzzing tests here
+
+ .../fonts/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf  | Bin
+ .../fonts/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf  | Bin
+ .../fonts/205edd09bd3d141cc9580f650109556cc28b22cb.ttf  | Bin
+ .../fonts/217a934cfe15c548b572c203dceb2befdf026462.ttf  | Bin
+ .../fonts/3511ff5c1647150595846ac414c595cccac34f18.ttf  | Bin
+ .../fonts/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf  | Bin
+ .../fonts/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf  | Bin
+ .../fonts/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf  | Bin
+ .../fonts/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf  | Bin
+ .../fonts/641bd9db850193064d17575053ae2bf8ec149ddc.ttf  | Bin
+ .../fonts/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf  | Bin
+ .../fonts/a34a9191d9376bda419836effeef7e75c1386016.ttf  | Bin
+ .../fonts/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf  | Bin
+ .../fonts/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf  | Bin
+ .../fonts/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf  | Bin
+ .../fonts/fab39d60d758cb586db5a504f218442cd1395725.ttf  | Bin
+ test/shaping/data/in-house/tests/fuzzed.tests           |  16
+ ----------------
+ 17 files changed, 16 deletions(-)
+
+commit 1487173dcf4137fb210b15d9a869aa1f0c626d15
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:30:38 2018 -0700
+
+    [fuzzing] Delete duplicate fonts
+
+ .../233c1e252e737ca79e03a9fd56b71aaa4a230f2b.ttf      | Bin 1048576 ->
+ 0 bytes
+ .../243798dd281c1c77c065958e1ff467420faa9bde.ttf      | Bin 225 ->
+ 0 bytes
+ .../9d8a94a67932a3ab75a596fc8b5c6d0392ca9e49.ttf      | Bin 4545 ->
+ 0 bytes
+ .../b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf      | Bin 3301 ->
+ 0 bytes
+ .../bbf4a308c402f0678c3e82844892a4da2ebe598f.ttf      | Bin 204 ->
+ 0 bytes
+ .../dd9f0c7c7c36f75a18be0cab1cddf8f3ab0f366b.ttf      | Bin 2786 ->
+ 0 bytes
+ .../ef2511f215aa3ca847cbfffbf861793b42170875.ttf      | Bin 1152 ->
+ 0 bytes
+ test/shaping/data/in-house/tests/fuzzed.tests         |   7 -------
+ 8 files changed, 7 deletions(-)
+
+commit 49c041f7c5b135cbcbd1663e18047afd54fc948b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:25:24 2018 -0700
+
+    Minor
+
+ test/fuzzing/clusterfuzz-testcase-6107935408390144 | Bin 16800 -> 0 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 36f38ea7033b4e52c6cd94a8a0d686a95c0cc148
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:24:03 2018 -0700
+
+    [gpos] Protect mark attachment against out-of-bounds
+
+    Not sure how can happen, but does...
+
+ src/hb-ot-layout-gpos-table.hh | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+commit 1147ce2392ac6b3d12fdabe69ac5da9bae97e30d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:18:32 2018 -0700
+
+    [fuzzing] Add more tests
+
+ .../fuzzing/fonts/clusterfuzz-testcase-6107935408390144 | Bin 0 ->
+ 16800 bytes
+ ...-testcase-minimized-harfbuzz_fuzzer-5973566991106048 | Bin 0 ->
+ 4047 bytes
+ ...-testcase-minimized-hb-shape-fuzzer-5633985665826816 | Bin 0 ->
+ 73 bytes
+ 3 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 12cbe195ae65656dbc9e32b4d50696bc4223136b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 16:13:53 2018 -0700
+
+    [aat] Another non-null offset
+
+ src/hb-aat-layout-ankr-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 87205ef935ede70365187549d133014669ea47f2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 15:40:44 2018 -0700
+
+    [aat] Make sure Lookup offset is never nulled
+
+    It has unbounded size...
+
+    Fixes https://oss-fuzz.com/v2/testcase-detail/5718889451749376
+
+ src/hb-aat-layout-ankr-table.hh |  2 +-
+ src/hb-aat-layout-common.hh     |  3 ++-
+ src/hb-aat-layout-kerx-table.hh | 18 ++++++++----------
+ src/hb-aat-layout-morx-table.hh |  4 ++--
+ src/hb-open-type.hh             | 12 ++++++------
+ 5 files changed, 19 insertions(+), 20 deletions(-)
+
+commit 1aa353e4fc79dfa880559ff75113ed58fac8392b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 15:26:51 2018 -0700
+
+    Fix tests
+
+ test/shaping/data/in-house/tests/fuzzed.tests | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 98d4ad02b97628e5a9a7bfe3187ccc3851c00b18
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 15:17:31 2018 -0700
+
+    [fuzzing] One more
+
+ test/fuzzing/clusterfuzz-testcase-6107935408390144 | Bin 0 -> 16800 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit e6f267c3dfe3e93dfc726266672da5a235fbd930
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 15:16:20 2018 -0700
+
+    [fuzzing] Add more clusterfuzz tests I had lying around
+
+ .../fonts/clusterfuzz-testcase-5517117891805184       | Bin 0 ->
+ 178 bytes
+ ...sterfuzz-testcase-hb-shape-fuzzer-5746142327865344 | Bin 0 ->
+ 219 bytes
+ ...sterfuzz-testcase-hb-shape-fuzzer-5750379279548416 | Bin 0 ->
+ 317 bytes
+ .../clusterfuzz-testcase-minimized-4884742786777088   | Bin 0 ->
+ 393 bytes
+ .../clusterfuzz-testcase-minimized-5255344882188288   | Bin 0 -> 65 bytes
+ .../clusterfuzz-testcase-minimized-5720051798769664   | Bin 0 ->
+ 1048576 bytes
+ .../clusterfuzz-testcase-minimized-5924299061854208   | Bin 0 ->
+ 2786 bytes
+ .../clusterfuzz-testcase-minimized-6460279560863744   | Bin 0 ->
+ 589 bytes
+ ...ized-blink_harfbuzz_shaper_fuzzer-5099655095123968 | Bin 0 -> 88 bytes
+ ...estcase-minimized-hb-shape-fuzzer-5650286710882304 | Bin 0 -> 76 bytes
+ ...stcase-minimized-hb-shape-fuzzer-5672261407735808} | Bin
+ 11 files changed, 0 insertions(+), 0 deletions(-)
+
+commit e53206271db4a83834433ab5f82d16815a18b998
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 17 01:42:04 2018 +0330
+
+    Add all the fonts found by fuzzers to the repo (#1258)
+
+ test/fuzzing/Makefile.am                           |   1 +
+ ...clusterfuzz-testcase-hb-fuzzer-4666056377368576 | Bin 0 -> 1152 bytes
+ ...clusterfuzz-testcase-hb-fuzzer-5662671558934528 | Bin 0 -> 242272
+ bytes
+ ...clusterfuzz-testcase-hb-fuzzer-6243458541944832 | Bin 0 -> 370187
+ bytes
+ ...clusterfuzz-testcase-hb-fuzzer-6303297511096320 | Bin 0 -> 4545 bytes
+ ...clusterfuzz-testcase-hb-fuzzer-6696647723581440 | Bin 0 -> 3266 bytes
+ ...z-testcase-minimized-hb-fuzzer-4523479581851648 | Bin 0 -> 322 bytes
+ ...z-testcase-minimized-hb-fuzzer-4535496598355968 | Bin 0 -> 2786 bytes
+ ...z-testcase-minimized-hb-fuzzer-4548492505645056 | Bin 0 -> 122 bytes
+ ...z-testcase-minimized-hb-fuzzer-4595692015190016 | Bin 0 -> 225 bytes
+ ...z-testcase-minimized-hb-fuzzer-4687441845813248 | Bin 0 -> 162 bytes
+ ...z-testcase-minimized-hb-fuzzer-4706238090706944 | Bin 0 -> 350 bytes
+ ...z-testcase-minimized-hb-fuzzer-4769173588672512 | Bin 0 -> 37 bytes
+ ...z-testcase-minimized-hb-fuzzer-4827735151083520 | Bin 0 -> 1384 bytes
+ ...z-testcase-minimized-hb-fuzzer-4841745322868736 | Bin 0 -> 660 bytes
+ ...z-testcase-minimized-hb-fuzzer-4884742786777088 | Bin 0 -> 393 bytes
+ ...z-testcase-minimized-hb-fuzzer-5216838347653120 | Bin 0 -> 157600
+ bytes
+ ...z-testcase-minimized-hb-fuzzer-5255344882188288 | Bin 0 -> 65 bytes
+ ...z-testcase-minimized-hb-fuzzer-5294584596791296 | Bin 0 -> 1602 bytes
+ ...z-testcase-minimized-hb-fuzzer-5303930168803328 | Bin 0 -> 7321 bytes
+ ...z-testcase-minimized-hb-fuzzer-5331901587914752 | Bin 0 -> 3301 bytes
+ ...z-testcase-minimized-hb-fuzzer-5388906574905344 | Bin 0 -> 9937 bytes
+ ...z-testcase-minimized-hb-fuzzer-5517117891805184 | Bin 0 -> 178 bytes
+ ...z-testcase-minimized-hb-fuzzer-5617496443846656 | Bin 0 -> 195 bytes
+ ...z-testcase-minimized-hb-fuzzer-5672141338968064 | Bin 0 -> 176 bytes
+ ...z-testcase-minimized-hb-fuzzer-5700697074958336 | Bin 0 -> 878 bytes
+ ...z-testcase-minimized-hb-fuzzer-5720051798769664 | Bin 0 -> 1048576
+ bytes
+ ...z-testcase-minimized-hb-fuzzer-5924299061854208 | Bin 0 -> 2786 bytes
+ ...z-testcase-minimized-hb-fuzzer-6023178755244032 | Bin 0 -> 2261 bytes
+ ...z-testcase-minimized-hb-fuzzer-6111685556305920 | Bin 0 -> 586 bytes
+ ...z-testcase-minimized-hb-fuzzer-6160439919509504 | Bin 0 -> 204 bytes
+ ...z-testcase-minimized-hb-fuzzer-6210176798425088 | Bin 0 -> 1420 bytes
+ ...z-testcase-minimized-hb-fuzzer-6260579246276608 | Bin 0 -> 700 bytes
+ ...z-testcase-minimized-hb-fuzzer-6264625609834496 | Bin 0 -> 1731 bytes
+ ...z-testcase-minimized-hb-fuzzer-6424351550210048 | Bin 0 -> 73 bytes
+ ...z-testcase-minimized-hb-fuzzer-6460279560863744 | Bin 0 -> 589 bytes
+ ...z-testcase-minimized-hb-fuzzer-6576177596596224 | Bin 0 -> 385 bytes
+ ...z-testcase-minimized-hb-fuzzer-6595199411159040 | Bin 0 -> 1862 bytes
+ ...z-testcase-minimized-hb-fuzzer-6624904746106880 | Bin 0 -> 42 bytes
+ ...z-testcase-minimized-hb-fuzzer-6723367514144768 | Bin 0 -> 1074 bytes
+ ...case-minimized-hb-shape-fuzzer-5630246225707008 | Bin 0 -> 109 bytes
+ ...case-minimized-hb-shape-fuzzer-5635082459545600 | Bin 0 -> 52 bytes
+ ...case-minimized-hb-shape-fuzzer-5652019562414080 | Bin 0 -> 49 bytes
+ ...case-minimized-hb-shape-fuzzer-5656511058018304 | Bin 0 -> 28 bytes
+ ...case-minimized-hb-shape-fuzzer-5659641787187200 | Bin 0 -> 3498 bytes
+ ...case-minimized-hb-shape-fuzzer-5668791174823936 | Bin 0 -> 3608 bytes
+ ...ase-minimized-hb-shape-fuzzer-56722614077358084 | Bin 0 -> 192 bytes
+ ...case-minimized-hb-shape-fuzzer-5674361600606208 | Bin 0 -> 518 bytes
+ ...case-minimized-hb-shape-fuzzer-5677421274071040 | Bin 0 -> 3608 bytes
+ ...case-minimized-hb-shape-fuzzer-5679244475105280 | Bin 0 -> 256 bytes
+ ...case-minimized-hb-shape-fuzzer-5685596677210112 | Bin 0 -> 58 bytes
+ ...case-minimized-hb-shape-fuzzer-5695615258853376 | Bin 0 -> 194 bytes
+ ...case-minimized-hb-shape-fuzzer-5696686572175360 | Bin 0 -> 256 bytes
+ ...case-minimized-hb-shape-fuzzer-5718889451749376 | Bin 0 -> 1680 bytes
+ ...case-minimized-hb-shape-fuzzer-5719982789361664 | Bin 0 -> 3608 bytes
+ ...case-minimized-hb-shape-fuzzer-5725129603022848 | Bin 0 -> 3608 bytes
+ ...case-minimized-hb-shape-fuzzer-5726089628876800 | Bin 0 -> 76 bytes
+ ...case-minimized-hb-shape-fuzzer-5729361857085440 | Bin 0 -> 2250 bytes
+ ...case-minimized-hb-shape-fuzzer-5733166795456512 | Bin 0 -> 78 bytes
+ ...case-minimized-hb-shape-fuzzer-5734736291430400 | Bin 0 -> 66 bytes
+ ...case-minimized-hb-shape-fuzzer-5740171484463104 | Bin 0 -> 186 bytes
+ ...case-minimized-hb-shape-fuzzer-5750379279548416 | Bin 0 -> 219 bytes
+ ...case-minimized-hb-shape-fuzzer-5762490181353472 | Bin 0 -> 101 bytes
+ ...ase-minimized-hb-subset-fuzzer-5359635656605696 | Bin 0 -> 393270
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-5521982557782016 | Bin 0 -> 1228 bytes
+ ...ase-minimized-hb-subset-fuzzer-5542653037903872 | Bin 0 -> 160249
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-5609911946838016 | Bin 0 -> 313 bytes
+ ...ase-minimized-hb-subset-fuzzer-5629878397829120 | Bin 0 -> 3746 bytes
+ ...ase-minimized-hb-subset-fuzzer-5651059347816448 | Bin 0 -> 2648 bytes
+ ...ase-minimized-hb-subset-fuzzer-5669437462544384 | Bin 0 -> 284427
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-5670861909524480 | Bin 0 -> 1298 bytes
+ ...ase-minimized-hb-subset-fuzzer-5696607199166464 | Bin 0 -> 28 bytes
+ ...ase-minimized-hb-subset-fuzzer-5711951464759296 | Bin 0 -> 284521
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-5747265633779712 | Bin 0 -> 177090
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-5750092395970560 | Bin 0 -> 72435 bytes
+ ...ase-minimized-hb-subset-fuzzer-5758598970343424 | Bin 0 -> 64 bytes
+ ...ase-minimized-hb-subset-fuzzer-6543700493598720 | Bin 0 -> 138425
+ bytes
+ ...ase-minimized-hb-subset-fuzzer-6651660668502016 | Bin 0 -> 15229 bytes
+ ...b-subset-get-codepoints-fuzzer-5203067375976448 | Bin 0 -> 16310 bytes
+ ...b-subset-get-codepoints-fuzzer-5630904853069824 | Bin 0 -> 580 bytes
+ ...b-subset-get-codepoints-fuzzer-5687638085337088 | Bin 0 -> 1206 bytes
+ ...b-subset-get-codepoints-fuzzer-5736539338833920 | Bin 0 -> 512 bytes
+ ...b-subset-get-codepoints-fuzzer-5973295416475648 | Bin 0 -> 109 bytes
+ ...b-subset-get-codepoints-fuzzer-6136125075750912 | Bin 0 -> 65816 bytes
+ ...b-subset-get-codepoints-fuzzer-6394290358976512 | Bin 0 -> 1868 bytes
+ test/fuzzing/run-shape-fuzzer-tests.py             |   4 +
+ test/shaping/data/in-house/tests/fuzzed.tests      |  84
+ +++++++++++++++++++++
+ 87 files changed, 89 insertions(+)
+
+commit 2137582c9696b6e38d70b4a0d4199b315c9fd4ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 14:46:07 2018 -0700
+
+    [morx] Reword ligation
+
+    Still fails MORX-41.  Am talking to Sascha to better understand
+    what CoreText
+    is doing.
+
+ src/hb-aat-layout-morx-table.hh                    | 25
+ ++++++++++++----------
+ test/shaping/data/text-rendering-tests/DISABLED    |  2 ++
+ .../data/text-rendering-tests/Makefile.sources     |  2 +-
+ 3 files changed, 17 insertions(+), 12 deletions(-)
+
+commit c53a25c6579a4d3fe8e6a6fc198d70add41035ec
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 13:57:35 2018 -0700
+
+    [morx] Comment
+
+ src/hb-aat-layout-morx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c46d42f8f2c303817467c6a4e19d69d0e433dba6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 13:39:54 2018 -0700
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   1 +
+ .../text-rendering-tests/fonts/TestMORXFourtyone.ttf     | Bin 0 ->
+ 2248 bytes
+ .../data/text-rendering-tests/tests/MORX-41.tests        |   4 ++++
+ 3 files changed, 5 insertions(+)
+
+commit 5eb7e7f6461bcf5b1e1d8ccb49eb904382762533
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 13:32:52 2018 -0700
+
+    Revert "[vector] Simplify Sort" and "More of the same"
+
+    This reverts commit de0b9a466490c2c13d6ec6f59d5122b0a87d3180.
+    This reverts commit 921f0e6ec722940a1e37660e1291aa69f9f39db8.
+
+    Annnnd, revert.  MSVC doesn't like it.
+
+ src/hb-vector.hh | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+commit 661340c475dc928f227d54b3f36eaf6f41c2b6e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 16 13:24:29 2018 -0700
+
+    [kern] Scale kern pairs before applying
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1255
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1252
+
+ src/hb-ot-kern-table.hh     | 18 ++++++++++++------
+ src/hb-ot-shape-fallback.cc |  2 +-
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+commit de0b9a466490c2c13d6ec6f59d5122b0a87d3180
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:20:26 2018 -0700
+
+    [vector] More of the same
+
+ src/hb-vector.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 921f0e6ec722940a1e37660e1291aa69f9f39db8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 22:19:17 2018 -0700
+
+    [vector] Simplify sort
+
+    Hopefully this fits fine with SFINAE with all our compilers.
+
+ src/hb-vector.hh | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit 61510b63c15e91d80e36a497260db0e2d6d36c66
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 16 14:17:21 2018 +0330
+
+    [test] Minor cleanup in test-multithread and test-ot-name (#1256)
+
+ test/api/CMakeLists.txt                       |  2 +-
+ test/api/Makefile.am                          |  2 +-
+ test/api/test-multithread.c                   |  6 ++-
+ test/api/{test-ot-nameid.c => test-ot-name.c} | 58
+ ++++++++++++++-------------
+ 4 files changed, 36 insertions(+), 32 deletions(-)
+
+commit 42b75dc3a701b13665115e2a234bfa5dedafef3f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 16 10:58:09 2018 +0330
+
+    [kerx] Minor, remove debug bit
+
+ src/hb-aat-layout-kerx-table.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 11703afce6cebbb4c5e7cdea59ca59a1787608b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 21:16:58 2018 -0700
+
+    [kerx] Fix Format6 sanitize
+
+    Fixes https://oss-fuzz.com/v2/testcase-detail/5650286710882304
+
+ src/hb-aat-layout-kerx-table.hh | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+commit 4c27da7638f6d072c3ff93223488c4ab316236c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 19:46:45 2018 -0700
+
+    [CBDT] Fix more offsetting
+
+    Fixes https://oss-fuzz.com/v2/testcase-detail/5750379279548416
+
+ src/hb-ot-color-cbdt-table.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 9ade3e7bb81be43b3c0811614b9b9533127894b0
+Merge: 6420ffe0 0f85edb7
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 15 14:03:23 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 6420ffe00fc4f4c6ffa63b80d961f70bc36c2caf
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 15 14:03:18 2018 -0700
+
+    fixed type casting bug
+
+ src/hb-cff-interp-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0f85edb7781f4d5ec2de676979be75a0f6559d80
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 11:15:54 2018 -0700
+
+    [morx] Another end-of-text corner case
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10990
+
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 55d5ea666c25f75e9b1bc2eb43cfb104a16ebe04
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 11:04:49 2018 -0700
+
+    [kerx] Merge clusters in Ligature
+
+ src/hb-aat-layout-morx-table.hh | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit bb35725cd760f07fdb0586453512a106e534b739
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 10:20:39 2018 -0700
+
+    [kerx/morx] More end-of-text protection
+
+ src/hb-aat-layout-kerx-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8f3048a1f838484babc4948754c16dda8f53daf1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 15 12:16:47 2018 +0330
+
+    [dump-emoji] minor
+
+ src/dump-emoji.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 27e095a613ed0a753231405cab887da19e9aecd1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 15 12:04:14 2018 +0330
+
+    [dump-emoji] better explaination of the usage
+
+ src/dump-emoji.cc | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+commit 8dc6296818e3a52c003852aa185f2b7eb6afa5d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 15 01:09:05 2018 -0700
+
+    [ot-font] Implement TrueType v_origin
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/537
+
+ src/hb-ot-font.cc                               | 31 +++++++++++++++++-
+ src/hb-ot-hmtx-table.hh                         | 43
+ ++++++++++++++++---------
+ test/shaping/data/in-house/tests/vertical.tests |  2 +-
+ 3 files changed, 59 insertions(+), 17 deletions(-)
+
+commit 6e07076fd094afc8c9c8ad8f08453e7882294592
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 22:22:45 2018 -0700
+
+    [blob] Fix UBSan error
+
+ src/hb-blob.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit fc812faaa96aa4e67814a92376b2da751d5a0aba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 21:32:09 2018 -0700
+
+    [CBDT] Fix more offsetting issues
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/960
+
+    dump-emoji still segfaults.  Needs debugging.
+
+ src/hb-ot-color-cbdt-table.hh | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+commit 6aee3bb87cee88525b745a640df294cb721245f6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 21:08:42 2018 -0700
+
+    [CBDT] Fix offset handling
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/960
+
+ src/hb-ot-color-cbdt-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit da744c6b3e79b778f414ec9f4d9070d06ec2a706
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 20:49:21 2018 -0700
+
+    [CBDT] More UnsizedArrayOf cleanup
+
+ src/hb-ot-color-cbdt-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2995b4465bce52b30de2cb6ba24cc80d8602413d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 20:37:57 2018 -0700
+
+    [CBDT] Simplify sanitize
+
+ src/hb-ot-color-cbdt-table.hh | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit 1c76c8f6ff7877e486f6e94d04b2dc65348b26d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 19:39:31 2018 -0700
+
+    [morx] Handle end-of-text conditions in Insertion
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10955
+
+ src/hb-aat-layout-morx-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 60c13976733ea05e71c66c486d62e31ffbb71bac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 19:36:46 2018 -0700
+
+    [buffer] Fix output_glyph at end of buffer
+
+    Part of https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10955
+
+ src/hb-buffer.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 7efa38257b6f79d1c6e2a9bad29c33af276abe29
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 19:30:44 2018 -0700
+
+    [aat] More protection against buffer fail
+
+ src/hb-aat-layout-common.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit e1add2a275a8afa5efc22aa44a4e62646f0b0ba4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 16:26:03 2018 -0700
+
+    [hmtx] Whitespace
+
+ src/hb-ot-hmtx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 62376a7d983442408059b0b8987e7ca8d1de154e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 15:20:50 2018 -0700
+
+    Ignore signed-integer-overflow while kerning
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1247
+
+ src/hb-ot-kern-table.hh | 1 +
+ src/hb.hh               | 9 +++++++++
+ 2 files changed, 10 insertions(+)
+
+commit 40f2b9355cf827c7b82ea5e55b112ce0032a9abf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 14:56:32 2018 -0700
+
+    [kerx] Fix Format1 sanitize
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10948
+
+ src/hb-aat-layout-kerx-table.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 44af1f93ee32e236a5c14085c72d3fa102a14f5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 14 14:52:17 2018 -0700
+
+    [aat] Whitespace
+
+ src/hb-aat-layout-common.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit db0d83ddc73ecf50ec4489fc10eddf3fa5835ae2
+Merge: 9228db06 56b8dd17
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Oct 13 17:25:38 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 9228db06f46908afd0e62f5964470c37c66ba91f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Oct 13 17:25:09 2018 -0700
+
+    added CFF1 Expert Encoding subset test & bug fixes
+
+ src/hb-ot-cff1-table.hh                     |   8 +++++++-
+ src/hb-subset-cff1.cc                       |  10 ++++++++--
+ test/api/fonts/cff1_expert.2D,F6E9,FB00.otf | Bin 0 -> 3096 bytes
+ test/api/fonts/cff1_expert.otf              | Bin 0 -> 3656 bytes
+ test/api/test-subset-cff1.c                 |  21 +++++++++++++++++++++
+ 5 files changed, 36 insertions(+), 3 deletions(-)
+
+commit 56b8dd17f677ffe97e4d917c47924e1ac7632c71
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 19:03:33 2018 -0400
+
+    [aat] Finish off massaging table
+
+ src/hb-aat-layout.cc | 163
+ +++++++++++++++++++++++++--------------------------
+ 1 file changed, 81 insertions(+), 82 deletions(-)
+
+commit e0c5e0d91bbc0c8b2bb547ba5cb118989affc617
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 18:37:14 2018 -0400
+
+    [aat] WIP remove feature mapping here from hb-coretext
+
+    Need to map enum values to numerics since we don't have CoreText
+    headers.
+
+ src/hb-aat-layout.cc |  94 +++++++++++++++++++++++++
+ src/hb-aat-layout.hh |  22 ++++++
+ src/hb-coretext.cc   | 189
+ +--------------------------------------------------
+ 3 files changed, 117 insertions(+), 188 deletions(-)
+
+commit cb057749131826dd89bc3b92527116a974ae3bbe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 17:03:32 2018 -0400
+
+    [coretext] Prepare AAT feature mapping to be moved
+
+ src/hb-coretext.cc | 39 ++++++++++++++++++++++-----------------
+ 1 file changed, 22 insertions(+), 17 deletions(-)
+
+commit de6e414c565de5f27b9da8c7b8b11f88659a4c42
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 13:48:22 2018 -0400
+
+    [kerx] Sanitize more
+
+ src/hb-aat-layout-kerx-table.hh | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+commit 71f76f2f39c88998b430b171c99b85818d4fa0ab
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 13:36:27 2018 -0400
+
+    [kerx] Fix-up previous commit
+
+    A "&" was missing.  Go back to using pointers that are less
+    error-prone.
+
+ src/hb-aat-layout-kerx-table.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 6d4b054234b4736ca9927268ee3e2d9a0f8f6ead
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 12:20:33 2018 -0400
+
+    [kerx] Use sanitizer instead of handcoded runtime sanitization
+
+ src/hb-aat-layout-kerx-table.hh | 24 +++++++++---------------
+ 1 file changed, 9 insertions(+), 15 deletions(-)
+
+commit 5733113662e668a25187e0042935d955e44fb488
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 12:16:12 2018 -0400
+
+    [kerx] Wire up context down to get_kerning
+
+ src/hb-aat-layout-kerx-table.hh | 32 ++++++++++++++------------------
+ 1 file changed, 14 insertions(+), 18 deletions(-)
+
+commit c4502833b711a76cce1af0c5bf075692b965c991
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 11:48:49 2018 -0400
+
+    [kerx] Use sanitizer.get_num_glyphs() instead of
+    face->get_num_glyphs()
+
+ src/hb-aat-layout-kerx-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit fc45e698f2d8a6d577f33b1e69a83714aceae528
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 11:39:12 2018 -0400
+
+    [kerx] Protext against overflows
+
+ src/hb-aat-layout-kerx-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit ed2ee78136c40de8e7b915dfdfd3ca92880912c3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 13 09:47:51 2018 -0400
+
+    [hangul] Fix use-after-free issue
+
+    out_info might have moved since we copied it's position into local
+    info var.
+
+    Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=894937
+
+ src/hb-ot-shape-complex-hangul.cc | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+commit 63109432cf61333e01af4ef5163d4202bb43f84d
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 13 14:00:05 2018 +0330
+
+    Cosmetic and minor changes
+
+ src/hb-buffer-serialize.cc   |   4 +-
+ src/hb-ot-cmap-table.hh      |   4 +-
+ src/hb-ot-layout-common.hh   |   4 +-
+ src/hb-ot-layout-gsubgpos.hh |   8 +--
+ src/hb-ot-layout.cc          | 127
+ +++++++++++++++++++------------------------
+ src/hb-ot-layout.h           |  25 +++++----
+ src/hb-ot-math-table.hh      |   8 +--
+ src/hb-ot-name.h             |   1 -
+ src/hb-ot-shape-complex.hh   |  18 +++---
+ 9 files changed, 93 insertions(+), 106 deletions(-)
+
+commit b64ef69b9e3d9cd4e81a2149cea3fe6e9e371cac
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Oct 12 14:14:21 2018 -0700
+
+    from encode_int removed assert hit by fuzzer
+
+    clamp the value instead
+
+ src/hb-subset-cff-common.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit c0a6814b49e376984a0cae9d385a6f6ba8c73579
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 12 16:05:56 2018 -0400
+
+    Touch up new API
+
+    New API:
+    +hb_ot_layout_feature_get_name_ids()
+    +hb_ot_layout_feature_get_characters()
+
+ src/hb-ot-layout.cc       | 16 +++++++++-------
+ src/hb-ot-layout.h        |  2 --
+ test/api/test-ot-nameid.c | 16 ++++++++++------
+ 3 files changed, 19 insertions(+), 15 deletions(-)
+
+commit 477bc9aafeaf89708d13a436869126351e2d9b50
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 12 15:52:31 2018 -0400
+
+    Add hb-ot-name.h
+
+    Actual name-fetching API to come later.
+
+    New API:
+    hb_name_id_t
+    HB_NAME_ID_INVALID
+
+ src/Makefile.sources       |  1 +
+ src/hb-ot-layout-common.hh |  2 +-
+ src/hb-ot-layout.h         | 12 ++---------
+ src/hb-ot-name.h           | 54
+ ++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot.h                |  1 +
+ 5 files changed, 59 insertions(+), 11 deletions(-)
+
+commit dc49bd8d813571fe16d9e5342e4a3926ff947bd6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Oct 12 03:00:59 2018 +0330
+
+    Add two APIs for getting stylistic set labels
+
+    * hb_ot_layout_feature_get_characters
+    * hb_ot_layout_feature_get_name_ids
+
+    However HarfBuzz currently doesn't expose an API for retrieving
+    the actual
+    information associated with NameId from the `name` table and that
+    should be
+    done separately.
+
+ docs/harfbuzz-sections.txt |   2 +
+ src/hb-ot-layout-common.hh |  14 +++++
+ src/hb-ot-layout.cc        | 133
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.h         |  29 ++++++++++
+ test/api/CMakeLists.txt    |   2 +
+ test/api/Makefile.am       |   1 +
+ test/api/fonts/cv01.otf    | Bin 0 -> 1956 bytes
+ test/api/test-ot-nameid.c  |  96 ++++++++++++++++++++++++++++++++
+ 8 files changed, 277 insertions(+)
+
+commit e9f9c0d81c73d8b6d87700aadb5b886bd289769a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 21:37:45 2018 -0400
+
+    [sanitize] Reorder condition to silence bogus gcc warning
+
+    Was givin a dozen of:
+
+    ../../src/hb-machinery.hh: In member function ‘bool
+    AAT::ankr::sanitize(hb_sanitize_context_t*) const’:
+    ../../src/hb-machinery.hh:307:23: warning: missed loop optimization,
+    the loop counter may overflow [-Wunsafe-loop-optimizations]
+         bool ok = --this->max_ops > 0 &&
+                   ~~~~~~~~~~~~~~~~~~~~~~
+            this->start <= p &&
+            ~~~~~~~~~~~~~~~~~~~
+            p <= this->end &&
+            ~~~~~~~~~~~~~~~^~
+            (unsigned int) (this->end - p) >= len;
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    I believe those are bogus, but this silences them and does not
+    introduce
+    logic issues I believe.
+
+ src/hb-machinery.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 1a6b5ac6c300ed2ccdcd8eadde433120f6e07f2a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 21:22:49 2018 -0400
+
+    Add HB_DEPRECATED_FOR and mark relevant symbols
+
+ src/hb-common.h     |  8 ++++++++
+ src/hb-deprecated.h | 10 +++++-----
+ src/hb-graphite2.h  |  2 +-
+ 3 files changed, 14 insertions(+), 6 deletions(-)
+
+commit c9413d7bb575093411b39ac21974795b6ad91454
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 21:19:39 2018 -0400
+
+    [graphite] Add HB_DEPRECATED annotation
+
+ src/hb-graphite2.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 68c86af187ff645a1305ac3b64832f3bb2350519
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 21:18:20 2018 -0400
+
+    Always compile deprecated symbols
+
+    We haven't been keeping this updated.  So, while we don't expose the
+    symbols in the headers if HB_DISABLE_DEPRECATED is defined, we still
+    always build them.
+
+ src/hb-font.cc | 4 ----
+ 1 file changed, 4 deletions(-)
+
+commit fc0153a1d4903a57b21974cc8d0b0a82d7bc43dc
+Merge: 7d99a6ce c5510000
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Oct 12 12:16:50 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 7d99a6cef80ec178c10dcf0e848394614c5e6912
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Oct 12 02:16:07 2018 -0700
+
+    overhauled error handling in CFF interpreter
+
+    minimized "if (error) return false" idiom
+
+ src/hb-cff-interp-common.hh      | 138
+ +++++++++++++++++++++++----------------
+ src/hb-cff-interp-cs-common.hh   |  43 ++++++------
+ src/hb-cff-interp-dict-common.hh |  72 +++++++++++---------
+ src/hb-cff1-interp-cs.hh         |  72 +++++++++++---------
+ src/hb-cff2-interp-cs.hh         |  50 +++++++-------
+ src/hb-ot-cff1-table.hh          |  91 +++++++++++---------------
+ src/hb-ot-cff2-table.hh          |  71 +++++++++-----------
+ 7 files changed, 281 insertions(+), 256 deletions(-)
+
+commit c55100000bc20d7c8319cfc54294215a923ffc25
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Oct 11 22:08:14 2018 -0400
+
+    Add missing colons to GObject annotations
+
+ src/hb-ot-tag.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 1e816d62efe1b3540ef605092b97794e68ec0832
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Oct 11 20:37:49 2018 -0400
+
+    Fix Indic script tags in Graphite
+
+ src/hb-graphite2.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit bf8469be9a8932cc407b60daf4d494fef46e233b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 20:45:00 2018 -0400
+
+    Attach CursivePositioning backwards, not forward
+
+    This is how Uniscribe does it.  So, adjust.  This is only relevant
+    to fonts that apply cursive positioning from a contextual lookup.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1181
+
+ src/hb-ot-layout-gpos-table.hh                      |  20
+ ++++++++++----------
+ .../9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf    | Bin 0 -> 2380 bytes
+ .../data/in-house/tests/cursive-positioning.tests   |   1 +
+ 3 files changed, 11 insertions(+), 10 deletions(-)
+
+commit bdb53ca24a5ad9671d8e29e17d1d8981505bd882
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 20:20:00 2018 -0400
+
+    [myanmar] Implement Zawgyi shaper
+
+    Enabled if script tag 'Qaag' is passed to HarfBuzz.  Disables mark
+    advance-zeroing and fallback mark-positioning.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1162
+
+ src/hb-ot-shape-complex-myanmar.cc                 |  22
+ +++++++++++++++++++++
+ src/hb-ot-shape-complex.hh                         |   5 +++++
+ src/hb.hh                                          |   8 ++++++++
+ test/shaping/data/in-house/Makefile.sources        |   1 +
+ .../ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf   | Bin 0 -> 1792 bytes
+ .../data/in-house/tests/myanmar-zawgyi.tests       |   1 +
+ 6 files changed, 37 insertions(+)
+
+commit 00c5c4a79dfb352a679a5c56bf9c756ab0fa98d2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 20:15:31 2018 -0400
+
+    [myanmar] Shuffle
+
+ src/hb-ot-shape-complex-myanmar.cc | 33 +++++++++++++++++----------------
+ 1 file changed, 17 insertions(+), 16 deletions(-)
+
+commit ec8f493bf9fefc33f027db24c4b175990b2d751c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 20:15:00 2018 -0400
+
+    [graphite] Remove assert
+
+ src/hb-graphite2.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 5646dcbd1125049c3af342fadfcfcbd523ce53d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 19:39:07 2018 -0400
+
+    Minor
+
+ src/hb-ot-tag.cc | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 788e1478557603d30966f12449eef0d0bd51c880
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 19:24:52 2018 -0400
+
+    [test] Add test for USE indic3
+
+ test/shaping/data/in-house/Makefile.sources              |   1 +
+ .../fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf   | Bin 0 ->
+ 3364 bytes
+ test/shaping/data/in-house/tests/use-indic3.tests        |   1 +
+ 3 files changed, 2 insertions(+)
+
+commit a11972787a2a90b541f92cc56bb885859390a0c0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 19:23:36 2018 -0400
+
+    Minor
+
+ test/shaping/record-test.sh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 654365dc894326f04abaaba415f48ca5ba2d1286
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 17:51:21 2018 -0400
+
+    Pass indic3 tags to USE shaper
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/539
+
+ src/hb-ot-shape-complex.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 28d091d045b042506a1ec2cdefe7cf0d718e8b22
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Oct 11 17:15:22 2018 -0400
+
+    Parse Indic3 tags
+
+ src/hb-ot-tag.cc       | 11 ++++++++---
+ test/api/test-ot-tag.c | 44 +++++++++++++++++++++++++-------------------
+ 2 files changed, 33 insertions(+), 22 deletions(-)
+
+commit 211cd3691ba01b1cb2eeb8a91ac3532181791a8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 17:31:29 2018 -0400
+
+    Remove remains of get-codepoint-fuzzer
+
+ test/fuzzing/CMakeLists.txt             |  7 +------
+ test/fuzzing/run-subset-fuzzer-tests.py | 12 ------------
+ 2 files changed, 1 insertion(+), 18 deletions(-)
+
+commit 120ed0272569e6a34172a511d4a5a70a3a18f1d2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 17:08:12 2018 -0400
+
+    [fuzzing] Fold get-codepoints-fuzzer into subset-fuzzer
+
+ test/fuzzing/Makefile.am                        | 16 ----------------
+ test/fuzzing/hb-subset-fuzzer.cc                |  5 +++++
+ test/fuzzing/hb-subset-get-codepoints-fuzzer.cc | 23
+ -----------------------
+ 3 files changed, 5 insertions(+), 39 deletions(-)
+
+commit 2c824d3644e16643c2bbe85fb88f9fb6fed53ce7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 16:41:01 2018 -0400
+
+    [aat] Fix two wrongs that made a right before!
+
+    Unfortunately our static asserts (DEFINE_SIZE_STATIC) don't actually
+    fail when used in templates, thanks to SFINAE.  Le sighs.
+
+    Probably fixes
+    https://oss-fuzz.com/v2/testcase-detail/5740171484463104
+
+ src/hb-aat-layout-common.hh | 4 ++--
+ src/hb-open-type.hh         | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit e940530c9723c3a581a5d5b31e5f419865dd6cc7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 15:56:17 2018 -0400
+
+    [aat] Fix mul overflow
+
+    Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10897
+
+ src/hb-aat-layout-common.hh | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+commit 1d995a340b9e17fc8dca7a3e88e0918de2d8f02c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 15:42:54 2018 -0400
+
+    Minor
+
+ test/api/hb-subset-test.h   | 6 ++----
+ test/api/test-multithread.c | 5 +----
+ test/fuzzing/main.cc        | 2 +-
+ 3 files changed, 4 insertions(+), 9 deletions(-)
+
+commit 0744a02cb12e4d800abb611dfa5d268bb2dfd9f3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 15:14:18 2018 -0400
+
+    [arabic] Update to latest UTR#53
+
+    From Lorna Evans: "That was a new character added to Unicode 11.0"
+
+ src/hb-ot-shape-complex-arabic.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 57b05210b1a8968d18ccbbe70879b2e11b6a09f2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 15:03:21 2018 -0400
+
+    [test] Fix use of deprecated symbols
+
+ test/api/test-ot-tag.c | 60
+ ++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 46 insertions(+), 14 deletions(-)
+
+commit ca37172ee3908bac12cc3d97768b95ae571530d2
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 11 11:55:55 2018 -0700
+
+    fixed leak
+
+ test/api/test-ot-extents-cff.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 4f9e36e8cf5d9d3d3e5a1ed46149355ee5f5e9fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 14:32:59 2018 -0400
+
+    [graphite] Remove deprecated symbol use
+
+ src/hb-graphite2.cc | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+commit da591f2a9d2ae2a5878d3b2ef78a6d589b19aab0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 14:30:15 2018 -0400
+
+    Whitespace
+
+ src/hb-ot-tag.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 4d205f0462b19f371df495b9cc12c0128f507de9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 14:25:48 2018 -0400
+
+    [graphite] Fix deva/dev2 resolution
+
+    See
+    https://github.com/harfbuzz/harfbuzz/pull/730#issuecomment-428277800
+
+ src/hb-graphite2.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 8061664ad1a5933098adc3bc1dca0b5be48586ef
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 14:16:55 2018 -0400
+
+    Add doc stubs for recently added API
+
+    Thanks to David Corbett who revamped our script and language
+    processing
+    and implemented full BCP 47 support.
+
+    https://github.com/harfbuzz/harfbuzz/pull/730
+
+    New API:
+    +hb_ot_layout_table_select_script()
+    +hb_ot_layout_script_select_language()
+    +HB_OT_MAX_TAGS_PER_SCRIPT
+    +HB_OT_MAX_TAGS_PER_LANGUAGE
+    +hb_ot_tags_from_script_and_language()
+    +hb_ot_tags_to_script_and_language()
+
+    Deprecated API:
+    -hb_ot_layout_table_choose_script()
+    -hb_ot_layout_script_find_language()
+    -hb_ot_tags_from_script()
+    -hb_ot_tag_from_language()
+
+ src/hb-ot-layout.cc | 10 ++++++++++
+ src/hb-ot-tag.cc    | 21 ++++++++++++++++-----
+ src/hb-ot-tag.h     | 10 ++++++++++
+ src/hb-unicode.h    |  2 +-
+ 4 files changed, 37 insertions(+), 6 deletions(-)
+
+commit cf975ac653bff369f4ed7ba7fc04fae6ce2cec95
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 14:07:44 2018 -0400
+
+    Remove use of deprecated function
+
+ src/hb-ot-layout.cc | 23 ++++++++++++-----------
+ src/hb-ot-layout.h  | 12 ++++++------
+ 2 files changed, 18 insertions(+), 17 deletions(-)
+
+commit 66790d64c7120b75c72bf91c769dc52d95858909
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Mon Sep 10 13:15:00 2018 -0400
+
+    Increase HB_OT_MAX_TAGS_PER_SCRIPT to 3
+
+    No script has 3 tags yet, but the plan is for the Indic scripts
+    to each
+    get a third tag someday.
+
+ src/hb-ot-tag.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bca7a16938609539e4adb5cdf943734b7dfa1561
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Mon Sep 10 12:05:51 2018 -0400
+
+    Update language system tag registry to OT 1.8.3
+
+ src/gen-tag-table.py   | 10 +++++++++-
+ src/hb-ot-tag-table.hh | 44 +++++++++++++++++++++++++++++++++-----------
+ 2 files changed, 42 insertions(+), 12 deletions(-)
+
+commit 7f1fbfe2e312f397db9271dd17a8e701489ffc79
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Mon Jul 23 21:19:23 2018 -0400
+
+    Add hb_ot_tags_to_script_and_language
+
+ docs/harfbuzz-sections.txt |  3 +-
+ src/hb-ot-map.cc           |  2 +-
+ src/hb-ot-tag.cc           | 75
+ ++++++++++++++++++++++++++++++++++++++++------
+ src/hb-ot-tag.h            | 18 +++++++----
+ test/api/test-ot-tag.c     | 33 ++++++++++++++++++--
+ 5 files changed, 112 insertions(+), 19 deletions(-)
+
+commit 3f8877473fb4c72a6f3edfcfc927b9993a5f3616
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Jul 19 13:48:07 2018 -0400
+
+    Switch on the first char of a complex language tag
+
+    This results in a tenfold speed-up for the common case of tags
+    that are
+    not complex, in the sense of `hb_ot_tags_from_complex_language`.
+
+ src/gen-tag-table.py   |  171 ++++--
+ src/hb-ot-tag-table.hh | 1580
+ ++++++++++++++++++++++++------------------------
+ 2 files changed, 922 insertions(+), 829 deletions(-)
+
+commit a754d44195021603306af2a296d06187eda95409
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Mon Jul 16 21:14:48 2018 -0400
+
+    Map Quechua languages to closest ones with tags
+
+    OpenType only officially maps four ISO 639 codes to Quechua languages,
+    but prior versions of HarfBuzz also mapped qu to 'QUZ '. Because qu
+    is a
+    macrolanguage, the mapping now applies to all individual Quechua
+    languages. OpenType calls 'QUZ ' "Quechua", but it really corresponds
+    to
+    Cusco Quechua, so the individual Quechua languages should not all
+    necessarily be mapped to it.
+
+ src/gen-tag-table.py   | 32 ++++++++++++++++++++++++++
+ src/hb-ot-tag-table.hh | 62
+ +++++++++++++++++++++++++++-----------------------
+ 2 files changed, 65 insertions(+), 29 deletions(-)
+
+commit 65d01f77552a5102ee114d9917fd2ecf091a35c3
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Jan 18 16:33:39 2018 -0500
+
+    Test deprecated tag fallback in a font
+
+    The font supports the deprecated tag 'DHV ' instead of 'DIV '. dv is
+    mapped to 'DIV ' and 'DHV ', in that order. The test specifies
+    `--language=dv`, demonstrating that if a font does not support
+    the first
+    OpenType tag mapped to a BCP 47 tag, it will fall back to the
+    next tag.
+
+ .../fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf    | Bin 0 ->
+ 956 bytes
+ test/shaping/data/in-house/tests/language-tags.tests      |   1 +
+ 2 files changed, 1 insertion(+)
+
+commit 7c7cb2a98907d99ca86bdbfca0bf9c48bfa4ed49
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Sat Jan 20 15:53:09 2018 -0500
+
+    Match extlang subtags
+
+    If the second subtag of a BCP 47 tag is three letters long, it denotes
+    an extended language. The tag converter ignores the language
+    subtag and
+    uses the extended language instead.
+
+    There are some grandfathered exceptions, which are handled earlier.
+
+ src/gen-tag-table.py   |  2 +-
+ src/hb-ot-tag-table.hh | 21 +++++++++++++++++++++
+ src/hb-ot-tag.cc       | 10 +++++++++-
+ test/api/test-ot-tag.c |  7 +++++++
+ 4 files changed, 38 insertions(+), 2 deletions(-)
+
+commit 2f1f961cc0f0f907916b4b00342d8a2dda8b4ee1
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Dec 8 22:45:52 2017 -0500
+
+    Autogenerate the BCP 47 to OpenType mappings
+
+    The new script, gen-tag-table.py, generates `ot_languages`
+    automatically
+    from the [OpenType language system tag registry][ot] and the [IANA
+    Language Subtag Registry][bcp47] with some manual modifications. If an
+    OpenType tag maps to a BCP 47 macrolanguage, all the macrolanguage's
+    individual languages are mapped to the same OpenType tag, except for
+    individual languages with their own OpenType mappings. Deprecated
+    BCP 47 tags are canonicalized.
+
+    [ot]:
+    https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
+    [bcp47]:
+    https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
+
+    Some OpenType tags correspond to multiple ISO 639 codes. The mapping
+    from ISO 639 codes lists OpenType tags in priority order, such
+    that more
+    specific or more likely tags appear first.
+
+    Some OpenType tags have no corresponding ISO 639 code in the
+    registry so
+    their mappings use BCP 47 subtags besides the language. For example,
+    any
+    BCP 47 tag with a fonipa variant subtag is mapped to 'IPPH', and
+    'IPPH'
+    is mapped back to und-fonipa.
+
+    Other OpenType tags have no corresponding ISO 639 code because it
+    is not
+    clear what they are for. HarfBuzz just ignores these tags.
+
+    One such ignored tag is 'ZHP ' (Chinese Phonetic). It probably means
+    zh-Latn. However, it is used in Microsoft JhengHei and Microsoft YaHei
+    with the script tag 'hani', implying that it is not a romanization
+    scheme after all. It would be simple enough to add this mapping to
+    gen-tag-table.py once a definitive mapping is determined.
+
+    The manual modifications are mainly either obvious mappings that the
+    OpenType registry omits or mappings for compatibility with previous
+    versions of HarfBuzz. Some of the old mappings were discarded, though,
+    for homophonous language names. For example, OpenType maps 'KUI ' to
+    kxu; previous versions of HarfBuzz also mapped it to kvd, because kvd
+    and kxu both happen to be called "Kui".
+
+    gen-tag-table.py also generates a function to convert multi-subtag
+    tags
+    like el-polyton and zh-HK to OpenType tags, replacing
+    `ot_languages_zh`
+    and the hard-coded list of special cases in
+    `hb_ot_tags_from_language`.
+    It also generates a function to convert OpenType tags to BCP 47,
+    replacing the hard-coded list of special cases in
+    `hb_ot_tag_to_language`.
+
+ src/Makefile.am        |    9 +-
+ src/Makefile.sources   |    1 +
+ src/gen-tag-table.py   | 1013 ++++++++++++++++++++++++
+ src/hb-ot-tag-table.hh | 1997
+ ++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-tag.cc       |  842 +-------------------
+ src/hb-ot-tag.h        |    2 +-
+ test/api/test-ot-tag.c |   66 +-
+ 7 files changed, 3092 insertions(+), 838 deletions(-)
+
+commit 2c7d4db7af16e228bb30eddf7334a524b74ae26c
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Dec 29 20:19:05 2017 +0800
+
+    Deprecate obsolete functions
+
+    `hb_ot_tags` replaces `hb_ot_tags_from_script` and
+    `hb_ot_tag_from_language`.
+
+    `hb_ot_layout_table_select_script` replaces
+    `hb_ot_layout_table_choose_script`.
+
+    `hb_ot_layout_script_select_language` replaces
+    `hb_ot_layout_script_find_language`.
+
+ docs/harfbuzz-sections.txt |  8 ++++----
+ src/hb-deprecated.h        | 23 +++++++++++++++++++++++
+ src/hb-ot-layout.h         | 15 ---------------
+ src/hb-ot-tag.h            |  8 --------
+ 4 files changed, 27 insertions(+), 27 deletions(-)
+
+commit 91067716f5e7b15d9a642f69019246c83fc7c108
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Dec 8 11:21:14 2017 -0500
+
+    Refactor the selection of script and language tags
+
+    The old hb-ot-tag.cc functions, `hb_ot_tags_from_script` and
+    `hb_ot_tag_from_language`, are now wrappers around a new function:
+    `hb_ot_tags`. It converts a script and a language to arrays of script
+    tags and language tags. This will make it easier to add new script
+    tags
+    to scripts, like 'dev3'. It also allows for language fallback chains;
+    nothing produces more than one language yet though.
+
+    Where the old functions return the default tags 'DFLT' and 'dflt',
+    `hb_ot_tags` returns an empty array. The caller is responsible for
+    using the default tag in that case.
+
+    The new function also adds a new private use subtag syntax for script
+    overrides: "x-hbscabcd" requests a script tag of 'abcd'.
+
+    The old hb-ot-layout.cc functions,`hb_ot_layout_table_choose_script`
+    and
+    `hb_ot_layout_script_find_language` are now wrappers around the new
+    functions `hb_ot_layout_table_select_script` and
+    `hb_ot_layout_script_select_language`. They are essentially the
+    same as
+    the old ones plus a tag count parameter.
+
+    Closes #495.
+
+ docs/harfbuzz-sections.txt |    5 +
+ src/hb-ot-layout.cc        |   43 +-
+ src/hb-ot-layout.h         |   16 +
+ src/hb-ot-map.cc           |   13 +-
+ src/hb-ot-tag.cc           | 1639
+ ++++++++++++++++++++++++--------------------
+ src/hb-ot-tag.h            |   11 +
+ test/api/test-ot-tag.c     |  107 +++
+ 7 files changed, 1070 insertions(+), 764 deletions(-)
+
+commit a03f5f4dfbbf885db567c3909241a55eb5869fce
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Dec 28 22:59:29 2017 +0800
+
+    Replace "ISO 639" with "BCP 47"
+
+    `hb_language_from_string` accepts not only ISO 639 but also BCP
+    47. Not
+    all ISO 639 codes are valid BCP 47 tags but the function does
+    not accept
+    overlong language subtags anyway.
+
+ src/hb-buffer.cc | 2 +-
+ src/hb-common.cc | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit ce6639cd27f79856466a5e8abf58f544f069e25d
+Merge: a6b6faf2 0b9d60e1
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 11 10:53:48 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit a6b6faf2b87f113fb23cf8e040f8b7875e2daf80
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 11 10:53:44 2018 -0700
+
+    Replaced CFF1 J subset font for better coverage
+
+    in api test-ot-extents-cff
+
+ test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf | Bin 0 ->
+ 3892 bytes
+ test/api/fonts/SourceHanSans-Regular.41,3041,4E9D.otf | Bin 5864 ->
+ 0 bytes
+ test/api/fonts/SourceHanSans-Regular.41,4C2E.otf      | Bin 0 ->
+ 2548 bytes
+ test/api/fonts/SourceHanSans-Regular.41,4E9D.otf      | Bin 5500 ->
+ 0 bytes
+ test/api/test-ot-extents-cff.c                        |  15
+ +++++++++++++++
+ test/api/test-subset-cff1.c                           |  18
+ +++++++++---------
+ 6 files changed, 24 insertions(+), 9 deletions(-)
+
+commit 0b9d60e1a1c4b7867ac907bbd7c004191a14e697
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 13:26:58 2018 -0400
+
+    [aat] Apply kerx if GPOS kern was not applied
+
+    Ned tells me this is what Apple does.
+
+ src/hb-ot-shape.cc | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+commit b59a428af08d6451a47f40ed01e594815ebf6303
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 13:24:17 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape.cc | 6 +++++-
+ src/hb-ot-shape.hh | 5 +++--
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+commit 100e95f48e3d137c654d206e858d6419ea62a12c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 11:30:45 2018 -0400
+
+    [trak] Add tests
+
+ test/shaping/data/in-house/Makefile.sources     |   1 +
+ test/shaping/data/in-house/fonts/TestTRAK.ttf   | Bin 0 -> 2456 bytes
+ test/shaping/data/in-house/tests/aat-trak.tests |   8 ++++++++
+ 3 files changed, 9 insertions(+)
+
+commit 04f72e8990ea61ffc6b62105c75e0a3e1b1ebab4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 11:25:07 2018 -0400
+
+    [trak] Implement extrapolation
+
+    This concludes trak, as well as AAT shaping support!
+
+ src/hb-aat-layout-trak-table.hh | 39
+ ++++++++++++++++++++-------------------
+ 1 file changed, 20 insertions(+), 19 deletions(-)
+
+commit d6a12dba6da6262fd9e5d8397b46ac8516136cae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 11:10:06 2018 -0400
+
+    [trak] Fix, and hook up
+
+    Works beautifully!  Test coming.
+
+ src/hb-aat-layout-common.hh     |  4 ++--
+ src/hb-aat-layout-trak-table.hh |  6 ++++--
+ src/hb-aat-layout.cc            | 25 ++++++++++++++++++++++++-
+ src/hb-aat-layout.hh            |  8 ++++++++
+ src/hb-ot-shape.cc              |  2 ++
+ 5 files changed, 40 insertions(+), 5 deletions(-)
+
+commit 3d7dea6dfdc9e75dcca100a79525aa3736dbe29c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 10:32:08 2018 -0400
+
+    [trak] Handle nSizes=0 and 1
+
+ src/hb-aat-layout-trak-table.hh | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+commit 451f3de521ff1b7f4d3b8ebb2cc0b95d88c9314a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 10:30:32 2018 -0400
+
+    [trak] Fix counting
+
+ src/hb-aat-layout-trak-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit a5be380cae9b49ed85c8620f1921209ef61a72ad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 10:29:02 2018 -0400
+
+    [trak] More
+
+ src/hb-aat-layout-trak-table.hh | 26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+commit d06c4a867f0d383d8c27f2957e646d9e3fe6853b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 10:22:01 2018 -0400
+
+    [trak] Only adjust around first glyph
+
+    Assumes graphemes only have one base glyph.
+
+ src/hb-aat-layout-trak-table.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 071a2cbcddcbafae9458e674c21db5001b39518d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 10:18:46 2018 -0400
+
+    [trak] Clean up
+
+ src/hb-aat-layout-trak-table.hh | 67
+ +++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 30 deletions(-)
+
+commit fbbd926dba163d9a2a6a62f380951f03363c2b14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 01:22:29 2018 -0400
+
+    [kerx] Implement Format4 action_type=1 contour-point-based attachment
+
+    Untested.
+
+    This concludes kerx table support!
+
+ src/hb-aat-layout-kerx-table.hh | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+commit b6bc0d4ff62e4509643db3b304306a72bbcb2c38
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 01:17:57 2018 -0400
+
+    [kerx] Implement Format4 action_type=2 coordinate-based attachment
+
+    Untested.
+
+ src/hb-aat-layout-kerx-table.hh | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+commit 1622ba5943d14b2d50d45dc17fb723f4c9ddb0bb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 01:14:18 2018 -0400
+
+    [kerx] Implement Format4 'ankr'-based mark attachment
+
+    Tested with Kannada MN:
+
+    $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0CCD,0C95,0CD6
+    [kn_ka.vattu=0+230|kn_ai_length_mark=1@326,0+607]
+
+ src/hb-aat-layout-common.hh     |  8 ++++++--
+ src/hb-aat-layout-kerx-table.hh | 20 +++++++++++++++++---
+ src/hb-aat-layout.cc            | 20 ++++++++++++++++----
+ src/hb-ot-layout-gpos-table.hh  |  4 ----
+ 4 files changed, 39 insertions(+), 13 deletions(-)
+
+commit 7bb4da7d9538f3d4b1d28030d43e0c3d720d821b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 00:52:07 2018 -0400
+
+    [aat] Wire up 'ankr' table to apply context
+
+ src/hb-aat-layout-common.hh | 7 +++++--
+ src/hb-aat-layout.cc        | 8 +++++++-
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+commit 28f0367aab648c486d6e8d0e13dbbb2af1b65dcc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 11 00:12:49 2018 -0400
+
+    [kerx] Flesh out Format4
+
+    Doesn't apply actions yet.
+
+ src/hb-aat-layout-kerx-table.hh | 122
+ ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 118 insertions(+), 4 deletions(-)
+
+commit 947962a287d9aca2cb509c11f44cb5150aa6daf1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 23:07:03 2018 -0400
+
+    [ankr] Implement table access
+
+ src/hb-aat-layout-ankr-table.hh | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+commit 7281cb3eeb00091c6e6085895afd4a38a0516f35
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 22:56:52 2018 -0400
+
+    [ankr] Start fixing
+
+ src/hb-aat-layout-ankr-table.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 34caadc5c78e3d09faf11ef60bfade8f64f55de2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 22:17:07 2018 -0400
+
+    Ugh. Re-enable accidentally disabled GPOS
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f7c45bc33ec1559c960a039b770d5c37bd82f057
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 22:15:13 2018 -0400
+
+    [kerx] Allow granularly disabling kerning
+
+ src/hb-aat-layout-kerx-table.hh | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+commit 2b72c4b63d29eea39b646c8a1a1cfc2db732e1a6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 21:53:14 2018 -0400
+
+    [kerx] Comment
+
+ src/hb-aat-layout-kerx-table.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 9f450f07b0a1593962e3b45d00f2cf93916f3466
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 21:46:58 2018 -0400
+
+    [kerx] Make Format1 work
+
+    Tested using Kannada MN:
+
+    $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD
+    [kn_ka.virama=0+1299|kn_ka.vattu=0+115|_blank=0@-115,0+385]
+
+    $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD
+    --features=-kern
+    [kn_ka.virama=0+1799|kn_ka.vattu=0+230|_blank=0+0]
+
+    I don't see the GPOS table in the font do the same.  ¯\_(ツ)_/¯
+
+ src/hb-aat-layout-kerx-table.hh | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+commit b5aa5dbb1158a5dfba29f7b119df9b4b319e8489
+Merge: af61c3b1 ab1f30bd
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 10 18:36:35 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit af61c3b10f83a00b4862cc0cb92fc9f0856e7dd6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 10 18:35:12 2018 -0700
+
+    added vsindex test & fixed process_vsindex
+
+ src/hb-cff2-interp-cs.hh                    |  12 +++++-----
+ test/api/fonts/AdobeVFPrototype_vsindex.otf | Bin 0 -> 7036 bytes
+ test/api/test-ot-extents-cff.c              |  33
+ ++++++++++++++++++++++++++++
+ 3 files changed, 40 insertions(+), 5 deletions(-)
+
+commit 504cb68fc972c7f606bf9fc62015376382f78f45
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 21:29:46 2018 -0400
+
+    Disable mark advance zeroing as well as mark fallback positioning
+    if doing kerx
+
+ src/hb-ot-shape.cc | 50
+ ++++++++++++++++++++++++++------------------------
+ 1 file changed, 26 insertions(+), 24 deletions(-)
+
+commit 84967537966a76297c89460d95e7336f1bfc332d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 21:18:37 2018 -0400
+
+    [kerx] Implement Format1
+
+    Untested.
+
+ src/hb-aat-layout-kerx-table.hh | 62
+ +++++++++++++++++++++++++++++++++--------
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ 2 files changed, 52 insertions(+), 12 deletions(-)
+
+commit c9165f5450b99e6d93e2a168b198384a221eef58
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 20:43:21 2018 -0400
+
+    [kerx] More UnsizedArrayOf<>
+
+ src/hb-aat-layout-kerx-table.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit ca54eba4846d0afda4601929556617a7ebe51714
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 20:41:16 2018 -0400
+
+    [kerx] Fix bound-checking error introduced a couple commits past
+
+ src/hb-aat-layout-kerx-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 339036dd970625e03696b4533ced1e25fc4fd131
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 20:37:22 2018 -0400
+
+    [kerx] Start fleshing out Format1
+
+ src/hb-aat-layout-kerx-table.hh | 59
+ +++++++++++++++++++++++++++++++++++------
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ 2 files changed, 52 insertions(+), 9 deletions(-)
+
+commit ab1f30bd059f1d2270793e9726b60666b328d2b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 20:10:20 2018 -0400
+
+    [kerx] Implement Format6
+
+    Untested.  The only Apple font shipping with this format is San
+    Francisco fonts
+    that use this for their kerx variation tables, which we don't support.
+
+ src/hb-aat-layout-kerx-table.hh | 73
+ +++++++++++++++++++++++++++++++++--------
+ 1 file changed, 60 insertions(+), 13 deletions(-)
+
+commit c9a2ce9e05f91730a2150b9214dc6a49f31555c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 20:00:44 2018 -0400
+
+    [kerx] Move bounds-checking to subtable length itself
+
+ src/hb-aat-layout-kerx-table.hh | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+commit 22955b23cdeb48e46cdffd0eb906a855a420c4d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 19:58:20 2018 -0400
+
+    [kerx] Start fleshing out Format6
+
+ src/hb-aat-layout-kerx-table.hh | 42
+ ++++++++++++++++++++++++++++++++---------
+ src/hb-open-type.hh             |  3 +++
+ 2 files changed, 36 insertions(+), 9 deletions(-)
+
+commit f6aaad9b4ffb42e6cd8398f6439fe420e393c8f6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 19:20:06 2018 -0400
+
+    [kerx] When rejecting variable kerning, also check for tupleCount
+
+ src/hb-aat-layout-kerx-table.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7ed5366d3cfca9c533250cb419e8cc878f32505d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 19:11:30 2018 -0400
+
+    [kerx] No-op
+
+    Tested that Format0 works with Kannada MN font:
+
+    $ make -j5 lib -s && HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc
+    -u 0C95,0CC2
+    [kn_ka=0+1000|kn_matra_uu=0@-30,0+1345]
+
+    $ make -j5 lib -s && HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u
+    0C95,0CC2 --features=-kern
+    [kn_ka=0+1030|kn_matra_uu=0+1375]
+
+    Note that GPOS does the same with 'dist' feature, and applies the
+    whole difference to the
+    same glyph:
+
+    $ make -j5 lib -s && ./hb-shape Kannada\ MN.ttc -u 0C95,0CC2
+    [kn_ka=0+970|kn_matra_uu=0+1375]
+
+    $ make -j5 lib -s && ./hb-shape Kannada\ MN.ttc -u 0C95,0CC2
+    --features=-dist
+    [kn_ka=0+1030|kn_matra_uu=0+1375]
+
+ src/hb-aat-layout-kerx-table.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 7fa69e92ca3dd9d8fa92aba0e01098165d2b7975
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 19:02:32 2018 -0400
+
+    Comment
+
+ src/hb-machinery.hh | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+commit 7e6e5bf6147596d6d096e2ba37f3a6eefd7429cd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 18:59:07 2018 -0400
+
+    Fix option string matching
+
+ src/hb-common.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5d34164d98f04816aafaa0abfc44cd899c7d70b3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 18:14:41 2018 -0400
+
+    [kern/kerx] Fix offset base
+
+    Disable kern Format2.
+
+    Fix kerx Format2.  Manually tested this with Tamil MN font and
+    it works:
+
+    $ HB_OPTIONS=aat ./hb-shape Tamil\ MN.ttc -u 0B94,0B95
+    [tgv_au=0+3435|tgc_ka=1@-75,0+1517]
+
+     HB_OPTIONS=aat ./hb-shape Tamil\ MN.ttc -u 0B94,0B95 --features=-kern
+    [tgv_au=0+3510|tgc_ka=1+1592]
+
+ src/hb-aat-layout-kerx-table.hh | 73
+ +++++++++++++++++++++++++----------------
+ src/hb-ot-kern-table.hh         |  7 ++++
+ 2 files changed, 52 insertions(+), 28 deletions(-)
+
+commit 60f86d32d7c735ccf783b382e18ecdc096eaa682
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 18:10:05 2018 -0400
+
+    [kerx] Don't loop over kerning subtables if kerning disabled
+
+ src/hb-aat-layout-kerx-table.hh | 12 ++++++++++++
+ src/hb-ot-shape.cc              |  4 ++--
+ src/hb-ot-shape.hh              |  1 +
+ 3 files changed, 15 insertions(+), 2 deletions(-)
+
+commit 38a7a8a89ed035a1d1fc34a675a1860ad660b6ff
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 17:44:46 2018 -0400
+
+    Allow HB_OPTIONS=aat to prefer AAT tables over OT
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/322
+
+ src/hb-common.cc   | 23 +++++++++++++++++++++--
+ src/hb-debug.hh    |  7 ++++---
+ src/hb-ot-shape.cc | 24 ++++++++++++++++--------
+ 3 files changed, 41 insertions(+), 13 deletions(-)
+
+commit 44f09afd5bd4f4f1ea47ca54ac9d605219b06910
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 17:32:32 2018 -0400
+
+    [kerx] Skip variation subtables
+
+ src/hb-aat-layout-kerx-table.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 1e8fdd285f90b7b715b6d9ca9222a3c91cbea6b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 16:32:35 2018 -0400
+
+    Remove HAVE_OT
+
+    We never tested compiling without it.  Just kill it.  We always build
+    our own shaper.
+
+ CMakeLists.txt        | 1 -
+ configure.ac          | 6 ------
+ src/Makefile.am       | 2 --
+ src/hb-shaper-list.hh | 2 --
+ src/hb.hh             | 2 --
+ test/api/Makefile.am  | 4 +---
+ test/api/test-c.c     | 5 +----
+ util/Makefile.am      | 4 ----
+ util/options.cc       | 4 ----
+ util/options.hh       | 2 --
+ 10 files changed, 2 insertions(+), 30 deletions(-)
+
+commit 7727e737566ddc826647e19fc645b296ad5a0cac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 13:24:51 2018 -0400
+
+    [kerx] Actually hook up, and fix crash
+
+ src/hb-aat-layout-common.hh     | 6 ++++++
+ src/hb-aat-layout-kerx-table.hh | 4 ++--
+ src/hb-ot-shape.cc              | 4 ++--
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+commit b3390990f508def9c375716614b92fc7b0038228
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 12:07:49 2018 -0400
+
+    Add per-subtable set-digests
+
+    This speeds up Roboto shaping by ~10%.  I was hoping for more.
+    Still, good defense against lookups with many subtables.
+
+ src/hb-null.hh               |   2 +-
+ src/hb-ot-layout-gsubgpos.hh | 108
+ +++++++++++++++++++++++--------------------
+ 2 files changed, 59 insertions(+), 51 deletions(-)
+
+commit e78549edfb4df617128a5f5ddd12692f1d0af4bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 11:54:48 2018 -0400
+
+    Move apply down into subtables accel
+
+ src/hb-ot-layout-gsubgpos.hh | 10 +++++++++-
+ src/hb-ot-layout.cc          | 17 +++--------------
+ 2 files changed, 12 insertions(+), 15 deletions(-)
+
+commit 78c09bf21335a0f2b538b37de6647af08e3b1161
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 11:50:46 2018 -0400
+
+    Move subtable array into lookup accel
+
+ src/hb-null.hh               |  2 +-
+ src/hb-ot-layout-gsubgpos.hh | 14 +++++++++++---
+ src/hb-ot-layout.cc          | 16 ++++++----------
+ 3 files changed, 18 insertions(+), 14 deletions(-)
+
+commit 97e5913d5ac2cd313fb3923e9602358d7f75f11d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 11:41:05 2018 -0400
+
+    Move more code
+
+ src/hb-ot-layout-gsubgpos.hh               | 17 +++++++++++++++++
+ src/hb-ot-layout.cc                        | 12 ++++++------
+ src/hb-ot-layout.hh                        | 20 ++------------------
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ 4 files changed, 26 insertions(+), 25 deletions(-)
+
+commit c8f2d9334c0f91ec30f1c7821eb44bb5149bd31c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 11:36:28 2018 -0400
+
+    Move code
+
+    In preparation to move add per-subtable set digests...
+
+ src/hb-ot-layout-gsubgpos.hh | 50 ++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.cc          | 57
+ ++++----------------------------------------
+ 2 files changed, 54 insertions(+), 53 deletions(-)
+
+commit a03850a3567d532c3a4d7655aa71bfe73dfb0e33
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:57:28 2018 -0400
+
+    Fix GPOS/kern interaction
+
+    Oops.  Was checking for kern feature in GSUB, not GPOS.
+
+ src/hb-ot-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d1be805e784dfaadf2ce9caa830a3f851fdd67da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:49:45 2018 -0400
+
+    More rewriting plan compile
+
+    Hopefully more clear.
+
+ src/hb-ot-shape.cc | 55
+ ++++++++++++++++++++++++++++++++++++++----------------
+ src/hb-ot-shape.hh |  1 -
+ 2 files changed, 39 insertions(+), 17 deletions(-)
+
+commit 961ab46b24ca9f3ef42a56398646191f106bf5bd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:42:10 2018 -0400
+
+    More reshuffle plan compile
+
+ src/hb-ot-shape.cc | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 2091b509e3e3b7fb7315539679fae81da2879280
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:41:08 2018 -0400
+
+    [kerx] Hook up to shaper
+
+ src/hb-aat-layout.cc | 31 ++++++++++++++++++++++++-------
+ src/hb-aat-layout.hh |  3 +++
+ src/hb-ot-shape.cc   |  6 ++++--
+ src/hb-ot-shape.hh   |  1 +
+ 4 files changed, 32 insertions(+), 9 deletions(-)
+
+commit 8d00c39bfc558895c63e22148d88db51cde39164
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:18:39 2018 -0400
+
+    [kern] Minor
+
+ src/hb-ot-shape-fallback.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit e655fd38cf20eefb1c071a52282a4caccb6f08ea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:16:09 2018 -0400
+
+    Apply TT or fallback kerning when GPOS does not have kern feature
+
+    Previously we only did if there was no GPOS whatsoever.  This applies
+    to Arial, Times New Roman, etc in Win7.  Was not kerning before.  It
+    is now.
+
+ src/hb-ot-shape.cc | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+commit 754cf440bf80ced36461a98a5d4607a700f44fd3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 10 10:04:05 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape-fallback.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 187df7d7a9a1d9cd67cb2f72d4d6ed8cae1eed61
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 10 17:12:52 2018 +0330
+
+    [circleci] Add an iOS bot (#1233)
+
+ .circleci/config.yml |  12 +++++
+ CMakeLists.txt       | 140
+ ++++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 100 insertions(+), 52 deletions(-)
+
+commit c06a5dff0b0f8d1c5aba53bcfd7fb0b680f1ca92
+Merge: 83c5298f 0537a401
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 9 22:00:10 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 83c5298f33e66cfd3d84d246297683f0de80c57d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 9 21:59:36 2018 -0700
+
+    added cff1_legacyops.otf as test-ot-extents-cff test case
+
+    fixed roll operator bugs uncovered by the test
+
+ src/hb-cff-interp-common.hh       |   4 ++--
+ test/api/fonts/cff1_legacyops.otf | Bin 0 -> 3104 bytes
+ test/api/test-ot-extents-cff.c    |  23 +++++++++++++++++++++++
+ 3 files changed, 25 insertions(+), 2 deletions(-)
+
+commit 0537a40193e803d50a99cd6b993d6d9301e84ebf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:35:07 2018 -0400
+
+    [kerx] Comment
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-ot-kern-table.hh         | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit 362d3241195bb7054c395fb4b029b6d55da4612a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:27:00 2018 -0400
+
+    [aat] Rename
+
+ src/hb-aat-layout-kerx-table.hh | 4 ++--
+ src/hb-aat-layout-morx-table.hh | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 54c9ecb92d196e62901eef3f8bc025c024ed16bb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:18:19 2018 -0400
+
+    [morx] Use subtable range for embedded sanitizer here as well
+
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit d35315cc028e70dd1b3ffc8cb079a2336b22a0c3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:17:32 2018 -0400
+
+    [aat] Fixup recent commit
+
+    For 329f2401082011007d9ce12b15ce0225cd267c57
+
+    max_ops is signed.
+
+ src/hb-aat-layout-common.hh | 2 +-
+ src/hb-machinery.hh         | 5 ++++-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+commit 948f59a13a4c643ae310f5fc643e29fefd6c3787
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:07:47 2018 -0400
+
+    [kerx] Use subtable range for runtime checks
+
+ src/hb-aat-layout-kerx-table.hh | 4 +++-
+ src/hb-machinery.hh             | 8 ++++++++
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+commit 329f2401082011007d9ce12b15ce0225cd267c57
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 23:02:53 2018 -0400
+
+    [aat] Set embedded sanitizer max ops really high
+
+    Since we consume it legitimately during shaping.
+
+ src/hb-aat-layout-common.hh | 1 +
+ src/hb-machinery.hh         | 2 ++
+ 2 files changed, 3 insertions(+)
+
+commit ad763074861da60ed51211931788ca5b27fc1512
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:57:00 2018 -0400
+
+    [kerx] Comment
+
+ src/hb-aat-layout-kerx-table.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit db9600bbe15035cea6c2d4e8e9d184a5e23e357e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:55:47 2018 -0400
+
+    [kerx] Remove junk
+
+ src/hb-aat-layout-kerx-table.hh | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+commit 27db859416c0362f211e2b42dc9a2ebb53b0e0f4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:52:41 2018 -0400
+
+    [kern/kerx] Adjust bounds check
+
+ src/hb-aat-layout-kerx-table.hh | 8 +++-----
+ src/hb-ot-kern-table.hh         | 8 +++-----
+ 2 files changed, 6 insertions(+), 10 deletions(-)
+
+commit c66f7f8c5deaac109e34bf65fc16cff92b74e69a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:49:33 2018 -0400
+
+    [kerx] Implement Format2 apply()
+
+    Still, not hooked.
+
+ src/hb-aat-layout-kerx-table.hh | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+commit 4b461785bdf356e4b5586cb6e5b226f47da04b7d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:46:30 2018 -0400
+
+    Fix check
+
+ src/hb-aat-layout-kerx-table.hh | 2 ++
+ src/hb-aat-layout.cc            | 4 +++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+commit 4df8eb200def767d342762654b96d5d9314e5b21
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:46:12 2018 -0400
+
+    [kern] Use kern subtable length for sanitizing in the accelerator
+
+ src/hb-ot-kern-table.hh | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+commit 8bff1d2994876a5202c8605d1cc37522431c6c84
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:39:31 2018 -0400
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 53e55945000347fb19168bb4c13a470d30d46251
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:35:22 2018 -0400
+
+    [kerx] Implement Format0 apply()
+
+    Not hooked up to be called yet.
+
+ src/hb-aat-layout-common.hh     |  6 ++++--
+ src/hb-aat-layout-kerx-table.hh | 29 ++++++++++++++++++++++++++---
+ src/hb-aat-layout.cc            |  6 ++++--
+ src/hb-aat-layout.hh            | 12 +++++++-----
+ src/hb-ot-shape.cc              |  2 +-
+ 5 files changed, 42 insertions(+), 13 deletions(-)
+
+commit 60318f87153b559e5da103f0bfcce6bad8bab3b0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 22:25:53 2018 -0400
+
+    Minor
+
+ src/hb-mutex.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 210f899acad1959d60892538ac1968a36dbbb51b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 21:56:37 2018 -0400
+
+    [kern] Sanitize 4 bytes, not 2
+
+ src/hb-ot-kern-table.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 588518ea51b2226bdb41417946848d18c3913a67
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 9 14:48:04 2018 -0700
+
+    fixed test-ot-extents-cff failure on some platforms
+
+ test/api/test-ot-extents-cff.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+commit be2f148da474d6dd30132c22dd467ea33a942edf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 16:24:50 2018 -0400
+
+    [ft] Use mutex to lock access to FT_Face
+
+    Makes our FT-backed hb_font_t safe to use from multiple threads.
+    Still,
+    the underlying FT_Face should NOT be used from other threads by client
+    or other libraries.
+
+    Maybe I add a lock()/unlock() public API ala PangoFT2 and cairo-ft.
+    Maybe not.
+
+ src/hb-ft.cc                | 18 +++++++++++++++++-
+ src/hb-mutex.hh             |  8 ++++++++
+ test/api/test-multithread.c |  7 ++-----
+ 3 files changed, 27 insertions(+), 6 deletions(-)
+
+commit d18c3c5861d40291077eb8b8667dc2f12b649cf2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 16:07:55 2018 -0400
+
+    [ft] Remove (probably) stale comment
+
+ src/hb-ft.cc | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit 7003b601afd02b0ba7e839510a7d0b886da09aaa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 15:55:26 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape-complex-arabic.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 07899435b8065d494e563f83e0a35300c828eefe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 15:39:51 2018 -0400
+
+    Install ot-funcs on newly created funcs
+
+    **Finally**!  Casual users can stop caring about font-funcs
+    completely now,
+    like they haven't been needing to care re unicode-funcs for a
+    few years.
+
+ src/hb-font.cc | 39 ++++++++++++++++++++++++++-------------
+ 1 file changed, 26 insertions(+), 13 deletions(-)
+
+commit 55153553675445e8aad06e363295d399aa79c54f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 15:12:09 2018 -0400
+
+    [ot-font] Don't pre-load cmap table
+
+    Now that we have get_h_advances() and get_nominal_glyphs()
+    implemented, the
+    overhead of doing a proper atomic load would be once per run, NOT
+    once per
+    glyph.  So, no need to pre-load the tables to avoid that overhead.
+
+    As such, hb_ot_font_set_funcs() has become really cheap.
+    Can *finally* make
+    it be default font functions on all newly created fonts!
+
+ src/hb-ot-font.cc | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+commit ec84460e46fdaa5f8a3c16c8d48dabe2b0c869da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 15:07:04 2018 -0400
+
+    [ot/ft] Implement get_nominal_glyphs() callback
+
+    Some more measurable speedup.  The recent commits' speedups are
+    as follows:
+
+    Testing with Roboto, ****when disabling kern and liga****:
+
+    Before:
+
+    FT --features=-kern,-liga
+    user↦   0m0.521s
+
+    OT --features=-liga,-kern
+    user↦   0m0.568s
+
+    After:
+
+    FT --features=-liga,-kern
+    user↦   0m0.428s
+
+    OT --features=-liga,-kern
+    user↦   0m0.470s
+
+    So, 17% speedup.
+
+    Note that FT callbacks are faster than OT these days since we added
+    an advance
+    cache to FT.  I don't think the difference is enough to justify
+    adding a cache
+    to OT.
+
+    When not disabling kern, the thing is three times slower, so the
+    speedups
+    are three times less impressive...  Still, 5% not bad for a codebase
+    that I
+    otherwise thought is optimized out.
+
+    Note that, because of this and other optimiztions in our main shaper,
+    disabling kern and liga, the OT shaper is now *faster* than the
+    fallback
+    shaper.  So, that's my recommendation to clients that need the
+    absolute
+    fastest...
+
+ src/hb-ft.cc      | 26 ++++++++++++++++++++++++++
+ src/hb-ot-font.cc | 24 ++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+)
+
+commit e883f52732a25f5495ec30656489954afd8cc3a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:50:57 2018 -0400
+
+    Call get_nominal_glyphs() for runs of simple clusters at a time
+
+    Even without FT or OT font funcs implementing get_nominal_glyphs(),
+    there's measurable
+    speedup.
+
+ src/hb-buffer.hh             | 20 +++++++++++++++++++-
+ src/hb-ot-shape-normalize.cc |  9 +++++++++
+ 2 files changed, 28 insertions(+), 1 deletion(-)
+
+commit 8008bca83b0bb310fc434dbdd339545af951193b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:38:23 2018 -0400
+
+    Whitespace
+
+ src/hb-font.hh               |  2 +-
+ src/hb-ot-shape-normalize.cc | 52
+ ++++++++++++++++++++++++--------------------
+ 2 files changed, 29 insertions(+), 25 deletions(-)
+
+commit 30c114ffec335770452e60729224b1634586c5b0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:37:08 2018 -0400
+
+    Avoid sort and recompose stages if all clusters simple
+
+    Even has measurable speedup...
+
+ src/hb-ot-shape-normalize.cc | 52
+ ++++++++++++++++++++++++--------------------
+ 1 file changed, 29 insertions(+), 23 deletions(-)
+
+commit 9f79365c3b183278d14352ba6241c7d4ec274984
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:36:25 2018 -0400
+
+    Fix warning
+
+    How come this one is not generated by clang everything bot?!
+
+    ../../../test/api/test-multithread.c:37:26: warning: initialization
+    discards ‘const’ qualifier from pointer target type
+    [-Wdiscarded-qualifiers]
+     static char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
+                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ../../../test/api/test-multithread.c:38:21: warning: initialization
+    discards ‘const’ qualifier from pointer target type
+    [-Wdiscarded-qualifiers]
+
+ test/api/test-multithread.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 24382debe893450088acd1e4b387ac31145d4553
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:33:24 2018 -0400
+
+    Rewrite main normalizer loop to isolate runs of simple clusters
+
+ src/hb-ot-shape-normalize.cc | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+commit b5371f18effbeb91565fd8c554c120b911641f0b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 14:12:59 2018 -0400
+
+    Inline decompose_cluster
+
+    Towards separating the common case into its own loop.
+
+ src/hb-ot-shape-normalize.cc | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+commit f5f505b5120c316f06306318c6c2f0db4496ba04
+Merge: 8b349040 4035158d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 9 10:10:35 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit b314c4e9abf4236c6650a63d1287471b61f64885
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 09:23:51 2018 -0400
+
+    [font] Add get_nominal_glyphs() callback (note the plural)
+
+    Unused as of now.  To be wired up to normalizer, which would remove
+    overhead and allow hb-ot-font initialization to become a no-op, so
+    we can enable it by default.
+
+ docs/harfbuzz-sections.txt |  3 +++
+ src/hb-font.cc             | 33 +++++++++++++++++++++++++++++++++
+ src/hb-font.h              | 24 ++++++++++++++++++++++++
+ src/hb-font.hh             | 13 +++++++++++++
+ 4 files changed, 73 insertions(+)
+
+commit ca6a317012a13ee84b58a69e14e74c94c5b158ff
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 09:06:07 2018 -0400
+
+    Minor
+
+ src/hb-font.cc | 6 +++---
+ src/hb-font.h  | 8 ++++----
+ src/hb-font.hh | 2 +-
+ 3 files changed, 8 insertions(+), 8 deletions(-)
+
+commit 4035158de46ce373b7521daf61c5b6df83312968
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Wed Jul 25 18:26:10 2018 +0800
+
+    test/api/test-subset-*.c: Fix build on pre-C99
+
+    Ensure that we have the variables at the beginning of the block.
+    These
+    are the only fixes that we need for building HarfBuzz on older
+    compilers.
+
+ test/api/test-collect-unicodes.c |  9 ++++++---
+ test/api/test-subset-glyf.c      | 19 +++++++++++++------
+ test/api/test-subset-hdmx.c      |  8 ++++++--
+ test/api/test-subset-hmtx.c      |  3 ++-
+ test/api/test-subset-post.c      |  3 ++-
+ test/api/test-subset-vmtx.c      |  6 ++++--
+ test/api/test-subset.c           | 12 +++++++++---
+ 7 files changed, 42 insertions(+), 18 deletions(-)
+
+commit 8e4ad1d7a0a35298ca04828ef1ef18b4c019ec03
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Wed Jul 25 18:12:34 2018 +0800
+
+    builds: Fix and clean up MSVC DLL builds
+
+    Instead of passing a CFLAG/CXXFLAG to define HB_EXTERN, define it
+    directly in src/hb.hh as __declspec(dllexport) extern when we are
+    building HarfBuzz as DLLs on Visual Studio.  Define HB_INTERNAL
+    as nothing without defining HB_NO_VISIBILITY when building HarfBuzz as
+    DLLs to avoid linker errors on Visual Studio builds.
+
+    Also "install" harfbuzz-subset.dll into $(PREFIX)\bin as the
+    hb-subset utility will depend on that DLL at runtime, when HarfBuzz is
+    built as DLLs.  Since it consists of private APIs that are subject to
+    change, we do not install its headers nor .lib file.
+
+ CMakeLists.txt |  7 ++++++-
+ src/hb.hh      | 10 ++++++++--
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+commit e640f3a6b16f41cee5f7868ec738fda01244e96a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 08:28:07 2018 -0400
+
+    Another old bot fix
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e4f27f368f8f0509fa47f6a28f3984e90b40588f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 08:20:10 2018 -0400
+
+    Try fixing older bots
+
+ src/hb-ot-shape-fallback.cc | 42
+ +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+commit bee93e269711a3eda4e7d762b730522564fe6e87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 08:01:49 2018 -0400
+
+    Add const to get_*_advances API
+
+    Ouch!
+
+ src/hb-font.cc    | 10 +++++-----
+ src/hb-font.h     |  8 ++++----
+ src/hb-font.hh    |  6 +++---
+ src/hb-ft.cc      |  2 +-
+ src/hb-ot-font.cc |  4 ++--
+ 5 files changed, 15 insertions(+), 15 deletions(-)
+
+commit eb2be97f864c726feaa2434e290f962ddfa97069
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 07:48:52 2018 -0400
+
+    Port test off deprecated API
+
+ test/api/test-shape.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit cc126f2817844a2e83e973129e5b2caa18de599f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 01:10:15 2018 -0400
+
+    Minor
+
+ src/Makefile.am          | 2 +-
+ test/shaping/Makefile.am | 2 ++
+ test/subset/Makefile.am  | 2 +-
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+commit b2fbe55b828ea5864bc0aed54db7109a2e189de2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 01:07:36 2018 -0400
+
+    [icu] Unbreak
+
+ src/hb-icu.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a353c1768dc1d7934b8ac293761620f561304bb2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 01:05:28 2018 -0400
+
+    Remove test for deprecated hb_set_invert()
+
+ test/api/test-set.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+commit a52bc039c33b3c01dbb96b815dc24df7f03bc4be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:56:33 2018 -0400
+
+    Properly remove deprecated stuff
+
+ src/hb-glib.cc | 15 ++++++---------
+ src/hb-icu.cc  | 15 ++++++---------
+ src/hb-ucdn.cc | 15 ++++++---------
+ 3 files changed, 18 insertions(+), 27 deletions(-)
+
+commit 8b349040e92b8894a7f8a609fac8070bcb110f96
+Merge: df964a09 fc509165
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 8 21:46:23 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit fc50916589a300e49183b5ee598e64ca28d0bd9a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:39:42 2018 -0400
+
+    Remove deprecated decompose_compatibility stuff
+
+ src/hb-glib.cc          | 31 +-----------------------------
+ src/hb-icu.cc           | 33 +-------------------------------
+ src/hb-ucdn.cc          |  8 +-------
+ test/api/test-unicode.c | 51
+ -------------------------------------------------
+ 4 files changed, 3 insertions(+), 120 deletions(-)
+
+commit eed737f6726d3408191a4e64592805b70d8bb247
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:33:30 2018 -0400
+
+    Remove deprecated eastasian_width
+
+ src/hb-glib.cc          |  8 +------
+ src/hb-icu.cc           | 19 +--------------
+ src/hb-ucdn.cc          |  9 +------
+ test/api/test-unicode.c | 64
+ -------------------------------------------------
+ 4 files changed, 3 insertions(+), 97 deletions(-)
+
+commit 47030b1855f04c0d75899ffb6f5021fea3c19b90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:30:45 2018 -0400
+
+    [ft/ot] Remove implementation of deprecated kerning funcs
+
+ src/hb-ft.cc      | 19 -------------------
+ src/hb-ot-font.cc | 13 -------------
+ 2 files changed, 32 deletions(-)
+
+commit 977c8a8e5c811995f47b0eb721199d0dc3689e48
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:22:08 2018 -0400
+
+    [kern] Minor
+
+ src/hb-ot-kern-table.hh | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+commit ed5cfa42c7fb8d5ff2d74bdb452a0590174f4e19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:20:35 2018 -0400
+
+    [kern] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit d219f899f4b2fb4b39ebc1dff9fb648fc5d6d112
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 9 00:01:09 2018 -0400
+
+    Deprecate font kern API
+
+ docs/harfbuzz-sections.txt | 16 +++++++-------
+ src/hb-deprecated.h        | 54
+ ++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-font.cc             |  3 +++
+ src/hb-font.h              | 51
+ -------------------------------------------
+ 4 files changed, 65 insertions(+), 59 deletions(-)
+
+commit a51958819fcf51ade3f8eb38001e680a419ebbba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 23:57:45 2018 -0400
+
+    Apply TrueType/OpenType kern table when GPOS kern feature is not
+    available
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/250
+
+ src/hb-ot-kern-table.hh     | 24 +++++++++++--------
+ src/hb-ot-layout.cc         | 57
+ ++++++++++++++++++++-------------------------
+ src/hb-ot-layout.hh         | 13 +++++++++++
+ src/hb-ot-shape-fallback.cc |  4 ++--
+ src/hb-ot-shape.cc          | 10 +++++---
+ src/hb-ot-shape.hh          |  1 +
+ 6 files changed, 62 insertions(+), 47 deletions(-)
+
+commit 09ad2613c8d8a60dac69a878c2d568adfea054c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 23:30:24 2018 -0400
+
+    Separate fallback kern vs mark positioning
+
+ src/hb-ot-shape-fallback.cc | 12 ++++++------
+ src/hb-ot-shape-fallback.hh | 12 ++++++------
+ src/hb-ot-shape.cc          | 15 ++++++++-------
+ src/hb-ot-shape.hh          |  4 ++--
+ 4 files changed, 22 insertions(+), 21 deletions(-)
+
+commit 3c23ff9b7c4241ec23054a95f1fdfbdef2c51f40
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 23:26:26 2018 -0400
+
+    [kern] Add kerning driver to TT kern table
+
+ src/hb-ot-kern-table.hh     | 19 +++++++++++++++++--
+ src/hb-ot-shape-fallback.cc |  2 +-
+ 2 files changed, 18 insertions(+), 3 deletions(-)
+
+commit 683c3a95330928129cfbb1488650f708414d68ba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 23:09:48 2018 -0400
+
+    [kern] Abstract away kerning machine
+
+ src/hb-font.hh              |  2 +-
+ src/hb-ot-kern-table.hh     | 71
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-shape-fallback.cc | 67
+ +++++++++++-------------------------------
+ 3 files changed, 89 insertions(+), 51 deletions(-)
+
+commit fb4f43838154a77912a9fc3437110c81e9d34aac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 22:44:16 2018 -0400
+
+    Add HB_DEPRECATED
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1232
+
+ src/hb-common.h     |  9 +++++++++
+ src/hb-deprecated.h | 12 ++++++------
+ 2 files changed, 15 insertions(+), 6 deletions(-)
+
+commit 80e3102b8a216f9a751d073f9a2f7900ca758086
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 22:41:08 2018 -0400
+
+    [kerx] Process coverage flags
+
+ src/hb-aat-layout-kerx-table.hh | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+commit 26d7305da7a7e2cf765b068f565836442872ffe7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 22:31:35 2018 -0400
+
+    Deprecate decompose_compatibility stuff
+
+ docs/harfbuzz-sections.txt |  7 +++---
+ src/hb-deprecated.h        | 63
+ ++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-unicode.h           | 47 ----------------------------------
+ 3 files changed, 67 insertions(+), 50 deletions(-)
+
+commit 42b51eee54f143854b7c6c3be5d84bfbbd895100
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 22:26:39 2018 -0400
+
+    Deprecate eastasian_width stuff
+
+ docs/harfbuzz-sections.txt |  5 +++--
+ src/hb-deprecated.h        | 37 +++++++++++++++++++++++++++++++++++++
+ src/hb-unicode.h           | 28 ----------------------------
+ 3 files changed, 40 insertions(+), 30 deletions(-)
+
+commit df964a09319bbf5b0a7528b906311726d4f640d6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 8 15:38:05 2018 -0700
+
+    fixed test-subset-cff2
+
+ src/hb-cff2-interp-cs.hh | 7 +++----
+ src/hb-ot-cff2-table.cc  | 2 +-
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+commit a90fd8b9feeee3b02d139f2e7db774766d7855cb
+Merge: b51418f5 e42cd58c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 8 15:07:58 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit b51418f596097aa5d1b28fb0a02b613c36bacd8e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 8 15:05:36 2018 -0700
+
+    added CFF2 get_extents
+
+    added source hb-ot-cff2-table.cc
+    augmented VariationData to return scalars
+    misc bug fixes, renaming, cleanup
+
+ src/Makefile.sources             |   2 +
+ src/hb-cff-interp-common.hh      |  37 ++++++-----
+ src/hb-cff-interp-cs-common.hh   | 134
+ +++++++++++++++++++-------------------
+ src/hb-cff-interp-dict-common.hh |   6 +-
+ src/hb-cff2-interp-cs.hh         | 102 ++++++++++++++++++++++++-----
+ src/hb-ot-cff1-table.hh          |   4 +-
+ src/hb-ot-cff2-table.cc          | 135
+ +++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-cff2-table.hh          |  71 ++++++++++++--------
+ src/hb-ot-face.cc                |   1 +
+ src/hb-ot-face.hh                |   1 +
+ src/hb-ot-font.cc                |   4 ++
+ src/hb-ot-layout-common.hh       |  28 +++++++-
+ src/hb-subset-cff1.cc            |   2 +-
+ src/hb-subset-cff2.cc            |   4 +-
+ test/api/test-ot-extents-cff.c   |  36 +++++++++++
+ 15 files changed, 426 insertions(+), 141 deletions(-)
+
+commit 286a45641fc6732bb7cab02f06c90396834541b1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 16:41:08 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape-normalize.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c0d3bf1bafe7b6d2e8f2798c1f55aaec71350d90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 16:32:44 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape.cc | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit 9c1bb81f5c5ca64ad1c665edd16947e4bc6f6c46
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 8 16:10:54 2018 -0400
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/DISABLED            | 3 ---
+ test/shaping/data/text-rendering-tests/Makefile.sources    | 2 +-
+ test/shaping/data/text-rendering-tests/tests/MORX-35.tests | 4 ++--
+ 3 files changed, 3 insertions(+), 6 deletions(-)
+
+commit 1a5a3325a26f4989ab8c4bb91515d4898ffa4631
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 23:08:39 2018 -0400
+
+    [kerx] Minor
+
+ src/hb-aat-layout-kerx-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit d62b4011cc600ade2b130f81a077dd08d4e4464f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:58:06 2018 -0400
+
+    [kern] Shout less
+
+ src/hb-ot-kern-table.hh | 36 +++++++++++++++++++-----------------
+ 1 file changed, 19 insertions(+), 17 deletions(-)
+
+commit c6bb3a588f493630b40d8823532b482f407bacbf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:52:53 2018 -0400
+
+    [kerx] Clean up Format2
+
+ src/hb-aat-layout-kerx-table.hh | 48
+ ++++++++---------------------------------
+ 1 file changed, 9 insertions(+), 39 deletions(-)
+
+commit 8aa83d97f9e7f63e2fcb4ae965b75a39961c7d87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:43:59 2018 -0400
+
+    [kern/kerx] Fix Format2 offsetting
+
+    "The values in the right class table are stored pre-multiplied by the
+    number of bytes in a single kerning value, and the values in the left
+    class table are stored pre-multiplied by the number of bytes in one
+    row. This eliminates needing to multiply the row and column values
+    together to determine the location of the kerning value. The array can
+    be indexed by doing the right- and left-hand class mappings,
+    adding the
+    class values to the address of the array, and fetching the kerning
+    value to which the new address points."
+
+ src/hb-aat-layout-kerx-table.hh | 2 +-
+ src/hb-ot-kern-table.hh         | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit ed2a404272bc99234c6f71f22b5a642834e59e6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:33:41 2018 -0400
+
+    [kerx] Clean up Format0
+
+ src/hb-aat-layout-kerx-table.hh | 48
+ +++++++++++------------------------------
+ 1 file changed, 12 insertions(+), 36 deletions(-)
+
+commit 4c3b19d52ec7a1fa46f8d0971e377a7d29b87e27
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:30:42 2018 -0400
+
+    Support HBUINT32 BinSearchArrayOf
+
+ src/hb-open-type.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit 456a68c506238e9c6b019244237d4443bd3589af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:28:45 2018 -0400
+
+    Move code
+
+ src/hb-aat-layout-common.hh | 105
+ --------------------------------------------
+ src/hb-open-type.hh         | 105
+ +++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 104 insertions(+), 106 deletions(-)
+
+commit 3515c8b187e2316dcf3abaefc84917b09449d485
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 22:27:00 2018 -0400
+
+    [aat] Rename
+
+ src/hb-aat-layout-common.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit e42cd58c997adafca5517faa9aacf651b90520f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 20:46:11 2018 -0400
+
+    Rename invisible_codepoint to invisible_glyph in API
+
+    Deleted recently added API:
+        hb_buffer_set_invisible_codepoint()
+        hb_buffer_get_invisible_codepoint()
+
+        hb-shape / hb-view --invisible-codepoint
+
+    New API:
+        hb_buffer_set_invisible_glyph()
+        hb_buffer_get_invisible_glyph()
+
+        hb-shape / hb-view --invisible-glyph
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1216
+
+ docs/harfbuzz-sections.txt |  4 ++--
+ src/hb-buffer.cc           | 12 ++++++------
+ src/hb-buffer.h            |  6 +++---
+ util/options.cc            |  2 +-
+ util/options.hh            |  6 +++---
+ 5 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 2a5cb37fdb43230217e055f3d7c770a35cfd5c21
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 20:36:46 2018 -0400
+
+    Revert "[morx] Fix MORX-35"
+
+    This reverts commit f62f6e90ad1f1a83f77771ad65ee1ffb79470a8a.
+
+ src/hb-aat-layout-morx-table.hh                         | 14
+ +++++---------
+ test/shaping/data/text-rendering-tests/DISABLED         |  3 +++
+ test/shaping/data/text-rendering-tests/Makefile.sources |  2 +-
+ 3 files changed, 9 insertions(+), 10 deletions(-)
+
+commit 14ebf8af0c04efcae6ca788ac85601bfe462f28d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 20:35:06 2018 -0400
+
+    [buffer] Improve shift_forward()
+
+    "Improve" is a strong word in this case though, I understand.
+
+ src/hb-buffer.cc | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+commit f62f6e90ad1f1a83f77771ad65ee1ffb79470a8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:06:53 2018 -0400
+
+    [morx] Fix MORX-35
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1224
+
+ src/hb-aat-layout-morx-table.hh                         | 14
+ ++++++++++----
+ test/shaping/data/text-rendering-tests/DISABLED         |  3 ---
+ test/shaping/data/text-rendering-tests/Makefile.sources |  2 +-
+ 3 files changed, 11 insertions(+), 8 deletions(-)
+
+commit 94368855c6bd7201d562cab3d2107685589e69c8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:52:12 2018 -0400
+
+    Remove some code
+
+    We use scratch-flags to short-circuit this function.  No need for
+    previous
+    early loop.
+
+ src/hb-ot-shape.cc | 16 +++-------------
+ 1 file changed, 3 insertions(+), 13 deletions(-)
+
+commit c07b91b812dc66b38b11329cd6a93258a3769f9e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:00:14 2018 -0400
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   6 +++++-
+ .../data/text-rendering-tests/fonts/TestMORXForty.ttf    | Bin 0 ->
+ 2408 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtyeight.ttf   | Bin 0 ->
+ 2444 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtynine.ttf    | Bin 0 ->
+ 2436 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtyseven.ttf   | Bin 0 ->
+ 2444 bytes
+ .../data/text-rendering-tests/tests/MORX-35.tests        |   4 ++--
+ .../data/text-rendering-tests/tests/MORX-37.tests        |   4 ++++
+ .../data/text-rendering-tests/tests/MORX-38.tests        |   4 ++++
+ .../data/text-rendering-tests/tests/MORX-39.tests        |   4 ++++
+ .../data/text-rendering-tests/tests/MORX-40.tests        |   4 ++++
+ 10 files changed, 23 insertions(+), 3 deletions(-)
+
+commit fdce1e15434f14b7f4802edd67f7af737cf2b075
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 14:01:33 2018 -0400
+
+    [kerx] Clean up kerx and KerxTable structures
+
+ src/hb-aat-layout-kerx-table.hh | 169
+ ++++++++++++++++++++++++++--------------
+ src/hb-aat-layout-morx-table.hh |   2 +-
+ 2 files changed, 113 insertions(+), 58 deletions(-)
+
+commit 71b65eb27dd0867f51d9906887b9e372eb37f54a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:41:52 2018 +0200
+
+    Add API for setting invisible-codepoint
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1216
+
+    New API:
+    hb_buffer_set_invisible_codepoint()
+    hb_buffer_get_invisible_codepoint()
+
+    hb-shape / hb-view --invisible-codepoint
+
+ docs/harfbuzz-sections.txt |  2 ++
+ src/hb-buffer.cc           | 42
+ ++++++++++++++++++++++++++++++++++++++++++
+ src/hb-buffer.h            |  7 +++++++
+ src/hb-buffer.hh           |  1 +
+ src/hb-ot-shape.cc         |  8 ++++----
+ util/options.cc            |  1 +
+ util/options.hh            |  3 +++
+ 7 files changed, 60 insertions(+), 4 deletions(-)
+
+commit 13da3be0b342e8e2f060eba8753c6957c477c4ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:23:45 2018 +0200
+
+    [ot-font] Load hmtx/vmtx lazily
+
+    Since we have get_*_advanes() API now, the overhead is once per shape,
+    not once per glyph.
+
+    Only cmap is warmed-up at set_funcs() time now.
+
+ src/hb-ot-font.cc | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit 856db4c9184e39c0457cc07c815f90058937c8a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 18:21:15 2018 +0200
+
+    Minor
+
+ src/hb-ot-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f92330b5e0b1a5a61768494bd7081e3fc235b182
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 17:51:50 2018 +0200
+
+    Minor
+
+ test/api/test-multithread.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit b2e398c077cf9437298bfe2ee53b7407a5865c14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Oct 7 16:31:33 2018 +0200
+
+    [coretext] Fix OS X check
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1230
+
+ src/hb-coretext.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 55942ad5c1ee999c9f590b8cc8fbde12e937aa6f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Sat Oct 6 14:49:44 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+ TODO                                               |  10 +--
+ configure.ac                                       |   2 +-
+ src/hb-aat-layout-common.hh                        |   4 +-
+ src/hb-aat-layout-morx-table.hh                    |   9 +-
+ src/hb-aat-layout.cc                               |   6 ++
+ src/hb-aat-layout.hh                               |   2 +
+ src/hb-face.cc                                     |   2 +-
+ src/hb-machinery.hh                                |   2 +-
+ src/hb-ot-cmap-table.hh                            |   2 +-
+ src/hb-ot-post-table.hh                            |   2 +-
+ src/hb-ot-shape.cc                                 |  27 ++++--
+ src/hb-ot-shape.hh                                 |   5 ++
+ src/hb-set.hh                                      |   4 +-
+ src/hb-subset.cc                                   |   2 +-
+ src/hb-vector.hh                                   | 100
+ ++++++++++++++-------
+ test/shaping/data/text-rendering-tests/DISABLED    |  35 +-------
+ .../data/text-rendering-tests/Makefile.sources     |  18 ++--
+ .../data/text-rendering-tests/extract-tests.py     |  18 +++-
+ .../text-rendering-tests/fonts/TestGSUBThree.ttf   | Bin 0 -> 1504 bytes
+ .../fonts/TestMORXThirtyfive.ttf                   | Bin 0 -> 1968 bytes
+ .../fonts/TestMORXThirtyfour.ttf                   | Bin 0 -> 3608 bytes
+ .../fonts/TestMORXThirtysix.ttf                    | Bin 0 -> 1836 bytes
+ .../fonts/TestMORXThirtythree.ttf                  | Bin 0 -> 1520 bytes
+ .../fonts/TestMORXTwentyfour.ttf                   | Bin 0 -> 1828 bytes
+ .../data/text-rendering-tests/tests/GSUB-3.tests   |   1 +
+ .../data/text-rendering-tests/tests/MORX-24.tests  |   1 +
+ .../data/text-rendering-tests/tests/MORX-32.tests  |   8 +-
+ .../data/text-rendering-tests/tests/MORX-33.tests  |   3 +
+ .../data/text-rendering-tests/tests/MORX-34.tests  |   1 +
+ .../data/text-rendering-tests/tests/MORX-35.tests  |   2 +
+ .../data/text-rendering-tests/tests/MORX-36.tests  |   1 +
+ test/shaping/run-tests.py                          |  19 ++--
+ util/view-cairo.hh                                 |   2 +-
+ 33 files changed, 173 insertions(+), 115 deletions(-)
+
+commit 7ee50af8366547c382047a30a94f7f5f739aabcb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 6 21:31:44 2018 +0200
+
+    [morx] Fix memory access issues with unsafe_to_break
+
+ src/hb-aat-layout-common.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit f58c5175890e666503b6f140d238e1abca91598e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 6 22:42:56 2018 +0330
+
+    Make msan output a little more readable
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e9abe33963739f753cdfb007eed40101ce33f550
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Oct 6 12:19:33 2018 +0330
+
+    Use tempfile in run-tests as a fix for Windows CI fails (#1228)
+
+ test/shaping/run-tests.py | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 0816a549789a1b647443c2b33cfda3f4400a0f87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Oct 6 02:40:57 2018 +0200
+
+    [uniscribe/coretext] Fix for previous change
+
+ src/hb-coretext.cc  |  2 +-
+ src/hb-uniscribe.cc | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 341206eb609202e4b2f0d03d29cb577ebe8390b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 5 18:39:48 2018 +0200
+
+    [vector] Make hb_vector_t relocatable / nestable
+
+    Ugly, but...
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1227
+
+ src/hb-face.cc          |  2 +-
+ src/hb-machinery.hh     |  2 +-
+ src/hb-ot-cmap-table.hh |  2 +-
+ src/hb-ot-post-table.hh |  2 +-
+ src/hb-set.hh           |  4 +--
+ src/hb-subset.cc        |  2 +-
+ src/hb-vector.hh        | 94
+ +++++++++++++++++++++++++++++++------------------
+ 7 files changed, 66 insertions(+), 42 deletions(-)
+
+commit 5469d80707d32c733b1c60f79ab2f217e879de55
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 5 18:21:08 2018 +0200
+
+    Add hb_vector_t::fini_deep ()
+
+ src/hb-vector.hh | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit 4831e615d173be9c7e140be0fa9017e4d9e499af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 5 18:14:13 2018 +0200
+
+    [morx] Fix memory access issue
+
+    If buffer was enlarged, info was being outdated.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1225
+
+ src/hb-aat-layout-common.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 5a41cf6be69adb0b5b29976a33c4c6dd6ce7afc5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 5 11:33:19 2018 +0200
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/DISABLED          |   3 +++
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   2 ++
+ .../text-rendering-tests/fonts/TestMORXThirtyfive.ttf    | Bin 0 ->
+ 1968 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtysix.ttf     | Bin 0 ->
+ 1836 bytes
+ .../data/text-rendering-tests/tests/MORX-35.tests        |   2 ++
+ .../data/text-rendering-tests/tests/MORX-36.tests        |   1 +
+ 6 files changed, 8 insertions(+)
+
+commit a62f37d6fa412b799b7247b813f6e65a968e7645
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Oct 5 02:49:29 2018 +0200
+
+    Change vendor features from Harf/Buzz to HARF/BUZZ
+
+    https://github.com/harfbuzz/harfbuzz/commit/a01194aaf4c15160330b4042066263b2c963b658#commitcomment-30772041
+
+    "The tag space of tags consisting of four uppercase letters (A-Z)
+    with no punctuation,
+    spaces, or numbers, is reserved as a vendor space. Font vendors may
+    use such tags to
+    identify private features."
+
+ src/hb-ot-shape.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e7a045e4db39e037badcab0ad1239c0cb56c1170
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 4 14:16:07 2018 -0700
+
+    fixed leak exposed by test-ot-extents-cff
+
+ src/hb-cff-interp-common.hh      | 3 +++
+ src/hb-cff-interp-dict-common.hh | 4 ++++
+ 2 files changed, 7 insertions(+)
+
+commit 6238edbd8b654d105bbd191dffabc7820f0a3223
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 4 13:59:36 2018 -0700
+
+    added CFF glyph extents API test
+
+ test/api/Makefile.am           |  1 +
+ test/api/test-ot-extents-cff.c | 65
+ ++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+
+commit 0222d57c357c775f25866653700b9dcb7d5bb807
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Oct 4 09:37:57 2018 -0700
+
+    tweaked previous warning fixes
+
+ src/hb-cff-interp-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 7b3ae5ffd202346cb3742fe0f8cfafe8c36a4bd5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 16:36:42 2018 +0200
+
+    More bot fixes
+
+ test/shaping/run-tests.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 310bdac4a08b99a25de6a16a20464873f90b52e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 16:31:14 2018 +0200
+
+    Fix a warning
+
+ util/view-cairo.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0abce58139bb58b8b97171db6387d2ac7eebdee0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 16:23:42 2018 +0200
+
+    [test] Choose 'ot' shaper specifically
+
+    Now that we added morx support, our OS X bot is running them through
+    CoreText
+    and failing (with a DoS / infinite loop no less!).  Always run
+    tests through
+    our own shaper.
+
+ test/shaping/run-tests.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c93d379bf2414eb6ee6d38fb9753ddf818a777ea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 13:28:13 2018 +0200
+
+    [TODO] Clean up
+
+ TODO | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+commit a01194aaf4c15160330b4042066263b2c963b658
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 13:00:37 2018 +0200
+
+    Enable two OpenType features, 'Harf' and 'Buzz'
+
+    One early, before script-specific features, one late, after.
+    Allows font
+    developers to detect us and behave differently if needed.
+
+ src/hb-ot-shape.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 55468ca01b4cdf274900fb752fbf9ae05a78705e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 12:13:55 2018 +0200
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   6 +++++-
+ test/shaping/data/text-rendering-tests/extract-tests.py  |  12
+ ++++++++++++
+ .../data/text-rendering-tests/fonts/TestGSUBThree.ttf    | Bin 0 ->
+ 1504 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtyfour.ttf    | Bin 0 ->
+ 3608 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtythree.ttf   | Bin 0 ->
+ 1520 bytes
+ .../text-rendering-tests/fonts/TestMORXTwentyfour.ttf    | Bin 0 ->
+ 1828 bytes
+ .../shaping/data/text-rendering-tests/tests/GSUB-3.tests |   1 +
+ .../data/text-rendering-tests/tests/MORX-24.tests        |   1 +
+ .../data/text-rendering-tests/tests/MORX-32.tests        |   8 ++++----
+ .../data/text-rendering-tests/tests/MORX-33.tests        |   3 +++
+ .../data/text-rendering-tests/tests/MORX-34.tests        |   1 +
+ test/shaping/run-tests.py                                |  15
+ +++++++++------
+ 12 files changed, 36 insertions(+), 11 deletions(-)
+
+commit 6ff8a8a10b62a54a87d53b0af66ccaba5d58b107
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 12:09:45 2018 +0200
+
+    Minor
+
+ test/shaping/data/text-rendering-tests/extract-tests.py | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 14ff3cbe0f30dea24e1bb175b1e8e41039f6afdc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 11:34:21 2018 +0200
+
+    Apply morx if there's no GSUB!
+
+ src/hb-ot-shape.cc                                 | 23 ++++++++++++----
+ src/hb-ot-shape.hh                                 |  5 ++++
+ test/shaping/data/text-rendering-tests/DISABLED    | 32
+ ----------------------
+ .../data/text-rendering-tests/Makefile.sources     | 14 +++++-----
+ 4 files changed, 29 insertions(+), 45 deletions(-)
+
+commit 3417037eb13a59dce6add0b1691ddb1b2b54c1e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Oct 4 11:08:15 2018 +0200
+
+    [aat] Add +hb_aat_layout_has_substitution
+
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ src/hb-aat-layout.cc            | 6 ++++++
+ src/hb-aat-layout.hh            | 2 ++
+ 3 files changed, 10 insertions(+)
+
+commit 1f14107f71a6c3da8270ed21c3588f945fa91733
+Author: Sascha Brawer <sascha@brawer.ch>
+Date:   Thu Oct 4 09:17:08 2018 +0200
+
+    Minor: Fix autoconf warning
+
+    Before this change, autoconf was emitting the following warnings:
+
+    ```
+    configure.ac:22: warning: AC_COMPILE_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_RUN_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_COMPILE_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_RUN_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_COMPILE_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_RUN_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_COMPILE_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    configure.ac:22: warning: AC_RUN_IFELSE was called before
+    AC_USE_SYSTEM_EXTENSIONS
+    ../../lib/autoconf/specific.m4:368: AC_USE_SYSTEM_EXTENSIONS is
+    expanded from...
+    configure.ac:22: the top level
+    ```
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7810bb1a59ea71afeed7ea489400801ebdf642e4
+Author: Sascha Brawer <sascha@brawer.ch>
+Date:   Thu Oct 4 09:24:08 2018 +0200
+
+    [morx] Only insert glyphs at mark when a mark has been set before
+
+    This reverts commit f4072e8cb81072cd6d51a2607efedb76c02e7db1.
+    https://github.com/harfbuzz/harfbuzz/issues/1195
+
+ src/hb-aat-layout-morx-table.hh | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+commit 3ef358909eb7e26ca9630e61c7ba142d9e94389e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 3 18:08:25 2018 -0700
+
+    fixed warnings
+
+ src/hb-cff-interp-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 1aeaee9dfc7ee3ca410919c41e55452a0b6b9bf6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 3 17:44:45 2018 -0700
+
+    fixed cff2 subset test data
+
+ test/api/fonts/AdobeVFPrototype.abc.nohints.otf | Bin 0 -> 7800 bytes
+ test/api/test-subset-cff2.c                     |   4 ++--
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 8be5a9186be3ca4c50c73f372be4dbad08ac1863
+Merge: d7b384ad 5de2d9cd
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Oct 3 17:06:18 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 5de2d9cdbdca870901c0ba9472f5b78c48ba0a58
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 4 02:14:18 2018 +0330
+
+    Minor, fix double-promotion warnings (#1221)
+
+ .circleci/config.yml        | 2 +-
+ src/dump-emoji.cc           | 2 +-
+ src/hb-common.cc            | 2 +-
+ src/hb-ot-var-fvar-table.hh | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+commit c2c7e6471ca912c91c82f6d71338082978f13dc6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Oct 4 00:29:40 2018 +0330
+
+    State our graphite2 dependency no-deprecated compile flag (#1220)
+
+ .circleci/config.yml | 2 +-
+ .travis.yml          | 2 --
+ configure.ac         | 2 +-
+ 3 files changed, 2 insertions(+), 4 deletions(-)
+
+commit e4e74c2751ac24178086cce2811d34d8019b6f85
+Author: mhosken <mhosken@users.noreply.github.com>
+Date:   Thu Oct 4 02:33:26 2018 +0700
+
+    Update Graphite API to latest (#1215)
+
+ src/hb-graphite2.cc | 28 +++++++++++++++++++++++++++-
+ 1 file changed, 27 insertions(+), 1 deletion(-)
+
+commit 81f5eb09eca010337ffb3369000a3d5c1e8e2cda
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 21:30:48 2018 +0200
+
+    Add emoji test for recent work
+
+ test/shaping/data/in-house/Makefile.sources             |   2 +-
+ .../fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf  | Bin 0 ->
+ 16596 bytes
+ test/shaping/data/in-house/tests/emoji-flag-tags.tests  |   2 --
+ test/shaping/data/in-house/tests/emoji.tests            |   4 ++++
+ 4 files changed, 5 insertions(+), 3 deletions(-)
+
+commit 9e2824cca0e42a53fafda7b2feb095986df40675
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 3 22:49:02 2018 +0330
+
+    [ci] Delete azure-pipelines
+
+    End of experiment, we might get back to it later
+
+ azure-pipelines.yml | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+commit b710ea4fdeb1a620b396bd07665fc129fe5fc074
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 21:17:59 2018 +0200
+
+    Clean Fitzpatrick hack
+
+ src/hb-ot-layout.hh |  2 +-
+ src/hb-ot-shape.cc  |  9 +++++++--
+ src/hb-unicode.hh   | 20 --------------------
+ 3 files changed, 8 insertions(+), 23 deletions(-)
+
+commit 95e5f1ae69036108f318b93b11d85b2ebc19109b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 21:11:13 2018 +0200
+
+    Unbreak Fitzpatrick
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1159
+
+ src/hb-ot-layout.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 03fb6dd4c7d12a98cc0ef325432658c3c76ab208
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 21:02:16 2018 +0200
+
+    Rewrite grapheme-formation in terms of new work
+
+    Also, don't attach ZWNJ to previous cluster.  Closer to Unicode
+    graphemes.
+
+ src/hb-coretext.cc                                 |  2 +-
+ src/hb-ot-shape.cc                                 | 48
+ ++++++----------------
+ .../in-house/tests/indic-joiner-candrabindu.tests  |  2 +-
+ .../data/in-house/tests/indic-joiners.tests        |  6 +--
+ 4 files changed, 18 insertions(+), 40 deletions(-)
+
+commit 68106b1d9b96caf79b0a778a7da75caf54e7d44a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:50:12 2018 +0200
+
+    Minor
+
+ src/hb-ot-layout.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 3f1c741b7a85d9c2d66e7f2446e988470c538b49
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:45:19 2018 +0200
+
+    [test] Split a test
+
+ .../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf | Bin 0 ->
+ 51924 bytes
+ .../fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf | Bin 74856 ->
+ 0 bytes
+ .../in-house/tests/mongolian-variation-selector.tests  |  17
+ ++++++++++++++++-
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+commit ba813aab0909375af0c8f8e0c34595680c2762a4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 3 21:52:15 2018 +0330
+
+    Update azure-pipelines.yml
+
+ azure-pipelines.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 06922acbc4558699e43a4ed98ffb21f1e84abfc6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:19:17 2018 +0200
+
+    Fix distcheck
+
+ src/Makefile.sources | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 4eea2e279b019ac627b2b9e2234a194957971022
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:16:03 2018 +0200
+
+    [thai] Set continuation on decomposed nikhahit
+
+ src/hb-ot-shape-complex-thai.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 8edc91022c3943fb306cee26ed6eb85381b5ea76
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:13:20 2018 +0200
+
+    [indic] Reset continuation on inserted dottedcircle
+
+ src/hb-ot-shape-complex-indic.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 2a6f15213ec30e5eb07465dd9dc81c2c386cb1e0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:09:14 2018 +0200
+
+    [buffer] Inline some more
+
+ src/hb-buffer.cc | 44 --------------------------------------------
+ src/hb-buffer.hh | 52
+ ++++++++++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 44 insertions(+), 52 deletions(-)
+
+commit 6f39c22029867c6d00cf70d7df242a28ca8f12bc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:06:32 2018 +0200
+
+    Add code
+
+ src/hb-ot-layout.hh | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 19d50aa2620f1464da8e00185b746e46fb0d80c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 20:05:28 2018 +0200
+
+    [indic] Simplify dottedcircle
+
+ src/hb-ot-shape-complex-indic.cc | 23 +++++++++++++++--------
+ 1 file changed, 15 insertions(+), 8 deletions(-)
+
+commit 3b7831851052ecf2611a115cc2b80ef970d83df8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 19:44:15 2018 +0200
+
+    [emoji] Mark emoji contination sequences as continuation
+
+    This adds a new grapheme bit.  Not used yet.
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1159
+
+ src/hb-ot-layout.hh | 83
+ +++++++++++++++++++++++++----------------------------
+ src/hb-ot-shape.cc  | 24 ++++++++++++++++
+ src/hb-unicode.hh   |  5 ----
+ 3 files changed, 63 insertions(+), 49 deletions(-)
+
+commit 123326e20a30a51e25339c2eca272e4e6c847742
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 19:19:51 2018 +0200
+
+    Dotted-circle all marks, not just non-spacing, at text beginning
+
+ src/hb-ot-shape.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 4146c00caa29e53ee9a29def151f12792ac76596
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Oct 3 21:26:58 2018 +0330
+
+    [test] Use an in-repo font for test-multithread (#1218)
+
+    As Khaled's suggestion, hard-coded font paths was only for my own
+    testing.
+
+ test/api/hb-subset-test.h   | 13 +++++++++----
+ test/api/test-multithread.c | 41
+ ++++++++++++++++++++++++++---------------
+ test/fuzzing/main.cc        |  6 ++++++
+ 3 files changed, 41 insertions(+), 19 deletions(-)
+
+commit fde9b8852d7cd6224afeffcfe363f4b445ab1ece
+Author: azure-pipelines[bot]
+<azure-pipelines[bot]@users.noreply.github.com>
+Date:   Wed Oct 3 17:47:05 2018 +0000
+
+    [ci] Add a test Azure Pipelines Linux bot
+
+    Related #1219
+
+ azure-pipelines.yml | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+commit 674560cf244054a7e8c16073a59aa1b01e1ba5ea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 19:10:28 2018 +0200
+
+    Fix build
+
+ src/test-unicode-ranges.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 45e55f70801e2ccd28e1ee30bdf5341b1ac6efe5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 18:07:49 2018 +0200
+
+    [indic] Fix clang everything
+
+ src/hb-ot-shape-complex-indic.cc | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+commit 4df02e3240ada0734748a47572baa2fc1c6afbd1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 17:54:09 2018 +0200
+
+    Minor
+
+ src/hb-ot-os2-unicode-ranges.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1e8f195b96765480007808da60789de9ac501c3b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 17:46:48 2018 +0200
+
+    [emoji] Add emoji Extended_Pictographic table and function
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/1159
+
+    .
+
+ src/Makefile.am                 |  12 +-
+ src/gen-emoji-table.py          |  64 ++++++++++
+ src/hb-ot-os2-table.hh          |   2 +-
+ src/hb-ot-os2-unicode-ranges.hh |   6 +-
+ src/hb-unicode-emoji-table.hh   | 269
+ ++++++++++++++++++++++++++++++++++++++++
+ src/hb-unicode.cc               |  16 +++
+ src/hb-unicode.hh               |  37 +++++-
+ 7 files changed, 398 insertions(+), 8 deletions(-)
+
+commit 1dc601b04a816a5b5ed12ae1c01ddcfd60a8398f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 17:27:46 2018 +0200
+
+    [os2] Minor rename/shuffle
+
+ ...unicode-ranges.py => gen-os2-unicode-ranges.py} |  2 +-
+ src/hb-ot-os2-unicode-ranges.hh                    | 45
+ +++++++++++-----------
+ 2 files changed, 24 insertions(+), 23 deletions(-)
+
+commit 7a1ab0464d3ee1ca5c9b31215fbffb8601ae860d
+Author: lantw44 <lantw44@gmail.com>
+Date:   Wed Oct 3 23:22:43 2018 +0800
+
+    Fix test-multithread build on FreeBSD (#1217)
+
+    Add the default font path used by FreeBSD ports.
+
+ test/api/test-multithread.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit df32eaae42b505b00de4a8b5efce9ab948bed847
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 14:44:25 2018 +0200
+
+    [indic] Disallow vowel mark combinations that spoof other vowel marks
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1019
+
+    New numbers:
+
+    BENGALI: 353725 out of 354188 tests passed. 463 failed (0.130722%)
+    DEVANAGARI: 707261 out of 707394 tests passed. 133 failed (0.0188014%)
+    GUJARATI: 366353 out of 366457 tests passed. 104 failed (0.0283799%)
+    GURMUKHI: 60729 out of 60747 tests passed. 18 failed (0.0296311%)
+    KANNADA: 951300 out of 951913 tests passed. 613 failed (0.0643966%)
+    MALAYALAM: 1048136 out of 1048334 tests passed. 198 failed
+    (0.0188871%)
+    ORIYA: 42327 out of 42329 tests passed. 2 failed (0.00472489%)
+    SINHALA: 271596 out of 271847 tests passed. 251 failed (0.0923313%)
+    TAMIL: 1091754 out of 1091754 tests passed. 0 failed (0%)
+    TELUGU: 970555 out of 970573 tests passed. 18 failed (0.00185457%)
+
+    Devanagari regressed because Uniscribe doesn't enforce the full set.
+
+    Tests added with the *-vowel-letters.txt files in tree and Noto fonts.
+
+ src/hb-ot-shape-complex-indic.cc                   | 256
+ ++++++++++++++++++++-
+ test/shaping/data/in-house/Makefile.sources        |   1 +
+ .../03e3f463c3a985bc42096620cc415342818454fb.ttf   | Bin 0 -> 2904 bytes
+ .../1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf   | Bin 0 -> 8188 bytes
+ .../2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf   | Bin 0 -> 2460 bytes
+ .../604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf   | Bin 0 -> 4120 bytes
+ .../738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf   | Bin 0 -> 2336 bytes
+ .../7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf   | Bin 0 -> 3452 bytes
+ .../881642af1667ae30a54e58de8be904566d00508f.ttf   | Bin 0 -> 2760 bytes
+ .../af85624080af5627fb050f570d148a62f04fda74.ttf   | Bin 0 -> 2656 bytes
+ .../tests/indic-vowel-letter-spoofing.tests        |  53 +++++
+ 11 files changed, 309 insertions(+), 1 deletion(-)
+
+commit 1b8d5e999192035c08f918aa1fcfcebdea67d82e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 14:44:19 2018 +0200
+
+    [thai] Minor
+
+ src/hb-ot-shape-complex-thai.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit d3d0cbd27831a6ea41b89f50d380296565c0016d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 13:54:21 2018 +0200
+
+    Typo
+
+ .../{bengali-vowel-leters.txt => bengali-vowel-letters.txt}
+ | 0
+ .../{gujarati-vowel-letter.txt => gujarati-vowel-letters.txt}
+ | 0
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 0dd9101fd0ddff80fff10ba98e93523aed95c8f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 13:26:26 2018 +0200
+
+    Minor
+
+ src/hb-ot-shape-complex-indic.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 9c4ffd10c4040ada9b1ffeb13c35f1330336359e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 12:53:54 2018 +0200
+
+    Minor
+
+ src/hb-ot-shape-complex.hh | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+commit bd1be8738fc4c73635cab7d77965264748d747cc
+Author: HinTak <htl10@users.sourceforge.net>
+Date:   Wed Oct 3 07:11:22 2018 +0800
+
+    Missing colon for gobject annotation
+
+    There should be a colon separating "(transfer full)" and the
+    rest. Warned by g-ir-scanner.
+
+ src/hb-face.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 75114e01d29b90f72a9398ed5dbc4298aba5a6b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Oct 3 12:29:56 2018 +0200
+
+    [use] Add Halant_Or_Vowel_Modifier category
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1102
+
+ src/gen-use-table.py                               |   7 +-
+ src/hb-ot-shape-complex-use-machine.hh             | 518
+ +++++++++++----------
+ src/hb-ot-shape-complex-use-machine.rl             |   9 +-
+ src/hb-ot-shape-complex-use-table.cc               |   4 +-
+ src/hb-ot-shape-complex-use.hh                     |   5 +-
+ .../28f497629c04ceb15546c9a70e0730125ed6698d.ttf   | Bin 0 -> 1496 bytes
+ .../shaping/data/in-house/tests/use-syllable.tests |   3 +
+ 7 files changed, 301 insertions(+), 245 deletions(-)
+
+commit d7b384ad0d0a3e1d35ef92a6e98a97bb9c367f48
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 21:08:36 2018 -0700
+
+    silence warning ^3
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e9cc71ac86bd771d9fcb2ee1eb620060db92ac1a
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 20:44:30 2018 -0700
+
+    silence warning ^2
+
+ src/hb-subset-cff1.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2700db9ade23cbf69d17a7a1802a7f144c25f8dc
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 15:05:26 2018 -0700
+
+    rm build files
+
+ build/test/api/.libs/test-collect-unicodes | Bin 14336 -> 0 bytes
+ build/test/api/.libs/test-multithread      | Bin 10936 -> 0 bytes
+ build/test/api/test-collect-unicodes       | 210
+ -----------------------------
+ build/test/api/test-multithread            | 210
+ -----------------------------
+ 4 files changed, 420 deletions(-)
+
+commit 51d5bf4ca2ebb9b8aa3b2777781e328fb93ceea7
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 14:38:06 2018 -0700
+
+    silence warnings
+
+ src/hb-cff-interp-cs-common.hh | 2 +-
+ src/hb-subset-cff1.cc          | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 35b64dfb57cac0d949363e9b19352dd4274c2584
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 14:13:36 2018 -0700
+
+    silence & fix new warnings
+
+ src/hb-cff-interp-dict-common.hh | 3 ++-
+ src/hb-cff1-interp-cs.hh         | 9 +++++----
+ src/hb-ot-cff-common.hh          | 4 ++--
+ src/hb-subset-cff1.cc            | 4 ++--
+ src/hb-subset-cff2.cc            | 4 ++--
+ 5 files changed, 13 insertions(+), 11 deletions(-)
+
+commit eed7e6bbc8e7be99d59a7822a1c37bc715c379b3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 13:45:14 2018 -0700
+
+    redefine OpCodes as define instead of enum
+
+    in order to eradicate duplicate enum warnings
+
+ src/hb-cff-interp-common.hh | 348
+ ++++++++++++++++++++++----------------------
+ 1 file changed, 174 insertions(+), 174 deletions(-)
+
+commit 9cdd70b344b9dc34a29aeca79028cbb5d949ca1d
+Merge: 3dd43f02 6353cc1f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Oct 2 13:43:21 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 6353cc1f83c862910860976411a1157f7ed571bc
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 2 21:39:19 2018 +0330
+
+    [circleci] Fix some of warnings from clang-everything bot (#1211)
+
+    * -Wshift-sign-overflow
+    * -Wmissing-prototypes
+
+ .circleci/config.yml             |  4 ++--
+ src/dump-emoji.cc                | 19 ++++++++++---------
+ src/hb-ucdn.cc                   |  3 +++
+ src/test-unicode-ranges.cc       |  4 ++--
+ test/fuzzing/hb-subset-fuzzer.cc | 32 +++++++++++++++++---------------
+ util/ansi-print.cc               |  4 ++--
+ 6 files changed, 36 insertions(+), 30 deletions(-)
+
+commit 9f1dee32fbad3b1486725c18570199156b57a94d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 18:56:20 2018 +0200
+
+    [tests] Allow test-runner to ignore shaping output
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1212
+
+ test/shaping/data/in-house/tests/fuzzed.tests | 46
+ +++++++++++++--------------
+ test/shaping/run-tests.py                     |  2 +-
+ 2 files changed, 24 insertions(+), 24 deletions(-)
+
+commit fef7af1e22efb399517137b35d0ba9f307411ca3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 18:46:13 2018 +0200
+
+    [tibetan] Remove unused Tibetan shaper
+
+ src/Makefile.sources               |  1 -
+ src/hb-ot-shape-complex-tibetan.cc | 63
+ --------------------------------------
+ src/hb-ot-shape-complex.hh         |  1 -
+ 3 files changed, 65 deletions(-)
+
+commit 32a438166fbccac6e0d9a615a492fc8cabfd21ab
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 18:43:29 2018 +0200
+
+    [tibetan] Route Tibetan through USE
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/933
+    https://github.com/harfbuzz/harfbuzz/issues/1012
+
+    Tibetan failures go from 0 to 2:
+
+    TIBETAN: 208467 out of 208469 tests passed. 2 failed (0.000959375%)
+
+ src/gen-use-table.py                 | 30 ++++++++++------
+ src/hb-ot-shape-complex-use-table.cc | 70
+ ++++++++++++++++++++++--------------
+ src/hb-ot-shape-complex.hh           |  8 +----
+ 3 files changed, 65 insertions(+), 43 deletions(-)
+
+commit 77792187be1405599e6aecfc3ed1fc771d505ddb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 18:20:16 2018 +0200
+
+    [khmer] Remove unused khmer_position()
+
+ src/dump-khmer-data.cc           | 8 +++-----
+ src/hb-ot-shape-complex-khmer.hh | 1 -
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+commit 5101abd42f4027edf182eddfa58c629b11c2a7f6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 17:49:06 2018 +0200
+
+    [indic/use] Factor common expressions in ragel machine
+
+    No machine change.
+
+ src/hb-ot-shape-complex-indic-machine.hh | 46
+ ++++++++++++++++----------------
+ src/hb-ot-shape-complex-indic-machine.rl | 10 ++++---
+ src/hb-ot-shape-complex-use-machine.hh   | 38 +++++++++++++-------------
+ src/hb-ot-shape-complex-use-machine.rl   | 20 +++++++-------
+ 4 files changed, 58 insertions(+), 56 deletions(-)
+
+commit 6f457f8370de5d96452ee3a2d1b0a97b025ef1d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 17:46:27 2018 +0200
+
+    [indic] Minor flip grammar around
+
+    No behavior change.
+
+ src/hb-ot-shape-complex-indic-machine.rl | 2 +-
+ src/hb-ot-shape-complex-use-machine.rl   | 1 -
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+commit d992982d23ef0c39ea42595ed0e8a4752977d1a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 17:16:01 2018 +0200
+
+    [indic] Add some confusable sequences from Unicode Standard
+
+ .../script-bengali/bengali-vowel-leters.txt        |  3 ++
+ .../devanagari-atomic-consonants.txt               | 33
+ ++++++++++++++++++++++
+ .../script-devanagari/devanagari-vowel-letters.txt | 17 +++++++++++
+ .../script-gujarati/gujarati-vowel-letter.txt      |  8 ++++++
+ .../script-gurmukhi/gurmukhi-vowel-letters.txt     |  9 ++++++
+ .../script-kannada/kannada-vowel-letters.txt       |  3 ++
+ .../script-malayalam/malayalam-vowel-letters.txt   |  5 ++++
+ .../script-oriya/oriya-vowel-letters.txt           |  3 ++
+ .../script-telugu/telugu-vowel-letters.txt         |  5 ++++
+ 9 files changed, 86 insertions(+)
+
+commit 40d5d19d5b875eef526a2a66892c3f638f633fa3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 17:04:05 2018 +0200
+
+    [ragel] Use ts/te (token-start / token-end) instead of manual tracking
+
+ src/hb-ot-shape-complex-indic-machine.hh   | 22 ++++++++++------------
+ src/hb-ot-shape-complex-indic-machine.rl   |  8 +++-----
+ src/hb-ot-shape-complex-khmer-machine.hh   | 22 ++++++++++------------
+ src/hb-ot-shape-complex-khmer-machine.rl   |  8 +++-----
+ src/hb-ot-shape-complex-myanmar-machine.hh | 22 ++++++++++------------
+ src/hb-ot-shape-complex-myanmar-machine.rl |  8 +++-----
+ src/hb-ot-shape-complex-use-machine.hh     | 22 ++++++++++------------
+ src/hb-ot-shape-complex-use-machine.rl     |  8 +++-----
+ 8 files changed, 52 insertions(+), 68 deletions(-)
+
+commit 9efddb9de821fc909a3ea8354f3dfd39c823e97b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 16:05:26 2018 +0200
+
+    Treat a base+mark... ligature as base, not ligature
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/746
+
+ src/hb-ot-layout-gsubgpos.hh | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+commit 3cca978723db43233d25402254d297dfccf991a3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 15:02:16 2018 +0200
+
+    Move code around
+
+ src/hb-ot-layout-gsub-table.hh |  3 ---
+ src/hb-ot-layout-gsubgpos.hh   | 22 +++++++++++-----------
+ 2 files changed, 11 insertions(+), 14 deletions(-)
+
+commit 0a371fee4d22ed63207aa76c00b05b75bbc95f5f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 14:48:39 2018 +0200
+
+    Minor
+
+ src/hb-ot-map.hh                   | 6 ++++--
+ src/hb-ot-shape-complex-arabic.cc  | 6 +++---
+ src/hb-ot-shape-complex-myanmar.cc | 4 ++--
+ src/hb-ot-shape-complex-use.cc     | 8 ++++----
+ src/hb-ot-shape.cc                 | 4 ++--
+ 5 files changed, 15 insertions(+), 13 deletions(-)
+
+commit 94d15528f80dbb7110d816fb5845f257f605a0be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 14:45:09 2018 +0200
+
+    Minor
+
+ src/hb-ot-map.hh   |  1 +
+ src/hb-ot-shape.cc | 39 ++++++++++++++++++---------------------
+ 2 files changed, 19 insertions(+), 21 deletions(-)
+
+commit 729f634728fb553300021d52089495271dfb19fd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 14:40:14 2018 +0200
+
+    Disable joiner-skipping when looking back for base to attach mark to
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1189
+
+ src/hb-ot-shape.cc                                      |   5 ++++-
+ test/shaping/data/in-house/Makefile.sources             |   1 +
+ .../fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf  | Bin 0 ->
+ 11492 bytes
+ .../data/in-house/tests/arabic-mark-attach.tests        |   1 +
+ 4 files changed, 6 insertions(+), 1 deletion(-)
+
+commit c36f3f5bef52e660541933f003fafa6e3a14785d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 14:34:29 2018 +0200
+
+    [arabic] Use manual-zwj instead of flipping joiners
+
+ src/hb-buffer.hh                  |  3 +--
+ src/hb-ot-layout.hh               | 12 ++----------
+ src/hb-ot-shape-complex-arabic.cc | 41
+ ++++++---------------------------------
+ 3 files changed, 9 insertions(+), 47 deletions(-)
+
+commit 48c513fec978819927535bc86b43be74315f746c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 14:17:42 2018 +0200
+
+    Minor
+
+ src/hb-ot-shape-complex-arabic.cc  |  2 +-
+ src/hb-ot-shape-complex-default.cc |  2 +-
+ src/hb-ot-shape-complex-hangul.cc  |  2 +-
+ src/hb-ot-shape-complex-hebrew.cc  | 14 +-------------
+ src/hb-ot-shape-complex-indic.cc   |  2 +-
+ src/hb-ot-shape-complex-indic.hh   |  2 --
+ src/hb-ot-shape-complex-khmer.cc   |  2 +-
+ src/hb-ot-shape-complex-myanmar.cc |  4 ++--
+ src/hb-ot-shape-complex-thai.cc    |  2 +-
+ src/hb-ot-shape-complex-tibetan.cc |  2 +-
+ src/hb-ot-shape-complex-use.cc     |  2 +-
+ src/hb-ot-shape-complex.hh         | 11 ++++-------
+ src/hb-ot-shape.cc                 |  8 ++++----
+ 13 files changed, 19 insertions(+), 36 deletions(-)
+
+commit cca757ae56d6a82cfad35edc6dbae58049a34f91
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 13:27:11 2018 +0200
+
+    Minor
+
+ src/hb-ot-shape.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 96eca87f89588126d3fa5c7f3884ae2f302a91e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 13:24:40 2018 +0200
+
+    Move things
+
+ src/hb-ot-shape.cc | 22 ++++++++++------------
+ src/hb-ot-shape.hh |  3 +++
+ 2 files changed, 13 insertions(+), 12 deletions(-)
+
+commit 588a4ac8bc9fd20464c7a77ead27ae34478c9bc8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 13:13:47 2018 +0200
+
+    Rename
+
+ src/hb-ot-face.cc | 20 +++++++-------
+ src/hb-ot-face.hh | 78
+ +++++++++++++++++++++++++++----------------------------
+ 2 files changed, 49 insertions(+), 49 deletions(-)
+
+commit 10b6c7c63870fa04cd8adcf9f38644c2a799db8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 13:11:18 2018 +0200
+
+    Minor include cleanup
+
+ src/hb-ot-shape-complex.hh | 1 +
+ src/hb-ot-shape.cc         | 4 +---
+ src/hb-ot-shape.hh         | 2 +-
+ 3 files changed, 3 insertions(+), 4 deletions(-)
+
+commit 1d1734e985e1f2a746b4fff0cd82d96d477577d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Oct 2 13:04:05 2018 +0200
+
+    Shuffle code around
+
+ src/hb-ot-shape-complex-hebrew.cc |  2 +-
+ src/hb-ot-shape-fallback.cc       |  2 +-
+ src/hb-ot-shape-normalize.cc      |  2 +-
+ src/hb-ot-shape.cc                | 32 ++++++++++++++++++++++++++++----
+ src/hb-ot-shape.hh                | 29 ++++++-----------------------
+ 5 files changed, 37 insertions(+), 30 deletions(-)
+
+commit bf5088b3dcd94106937290c180f3f40bc8524b48
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 2 11:07:06 2018 +0330
+
+    Minor, fix -Weverthing bot warnings (#1210)
+
+ test/api/test-buffer.c      | 8 ++++----
+ test/api/test-multithread.c | 3 +--
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+commit d27e5ec3a236b8eb37ef9ce558ad54077e46b003
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Tue Oct 2 08:25:29 2018 +0200
+
+    Skip BOM in the Python sample file
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1208
+
+ src/sample.py | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit f9ea3dc4c6e85c417dd4c8546e5ebe02b67131b9
+Author: HinTak <htl10@users.sourceforge.net>
+Date:   Tue Oct 2 06:43:06 2018 +0100
+
+    Missing "out" indicator (#1209)
+
+    Missing "out" indicator. Affect gobject introspection.
+
+ src/hb-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9742679b8253919f8bfec8a77532092044e951aa
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 2 03:20:48 2018 +0330
+
+    [circleci] Remove some of the not needed flags
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f72b748371da2d7ce327a5d15feea46960aa7dd3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Oct 2 00:16:08 2018 +0330
+
+    [circleci] Fix "msan" and "everything" bots (#1205)
+
+ .circleci/config.yml                    | 13 ++++++-------
+ src/check-symbols.sh                    |  2 --
+ test/fuzzing/main.cc                    | 22 +++++++++-------------
+ test/fuzzing/run-shape-fuzzer-tests.py  |  2 --
+ test/fuzzing/run-subset-fuzzer-tests.py |  2 --
+ 5 files changed, 15 insertions(+), 26 deletions(-)
+
+commit 8bf4027d23318c7e1ff7fe9f5e7ad8b0380e5415
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 20:05:00 2018 +0200
+
+    [indic] Remove Consonant_Medial from grammar and code
+
+    The only Indic CM is U+0A75 GURMUKHI SIGN YAKASH, which Uniscribe
+    doesn't treat
+    specially, and font designers design for that.  So, do the same.
+
+ src/hb-ot-shape-complex-indic-machine.hh | 1244
+ ++++++++++++++----------------
+ src/hb-ot-shape-complex-indic-machine.rl |   10 +-
+ src/hb-ot-shape-complex-indic.cc         |    2 +-
+ src/hb-ot-shape-complex-indic.hh         |    6 +-
+ 4 files changed, 589 insertions(+), 673 deletions(-)
+
+commit ab4c37f73a7d4fcf48584cda3fff94e98a672086
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 19:35:48 2018 +0200
+
+    [khmer] Add mark-ordering tests
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/667
+
+ test/shaping/data/in-house/Makefile.sources        |   2 ++
+ .../b6031119874ae9ff1dd65383a335e361c0962220.ttf   | Bin 0 -> 2564 bytes
+ .../data/in-house/tests/khmer-mark-order.tests     |  25
+ +++++++++++++++++++++
+ 3 files changed, 27 insertions(+)
+
+commit 51436547162a18e88144e7125ad6ce4a69a08d4b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 19:09:58 2018 +0200
+
+    [khmer] Rewrite grammar completely
+
+    Based on experimenting with Uniscribe to extract grammar and
+    categories.
+
+    Failures down from 44 to 35:
+
+    KHMER: 299089 out of 299124 tests passed. 35 failed (0.0117008%)
+
+    We still don't enforce the one-matra rule pre-decomposition,
+    but enforce
+    an order and one-matra-per-position post-decomposition.
+
+    https://github.com/harfbuzz/harfbuzz/issues/667
+
+ src/hb-ot-shape-complex-indic.hh         |   2 +-
+ src/hb-ot-shape-complex-khmer-machine.hh | 300
+ ++++++++++++++++++++-----------
+ src/hb-ot-shape-complex-khmer-machine.rl |  42 +++--
+ src/hb-ot-shape-complex-khmer.cc         |   4 +-
+ src/hb-ot-shape-complex-khmer.hh         |  99 +++++-----
+ 5 files changed, 270 insertions(+), 177 deletions(-)
+
+commit 3dd43f0234febd434d89927adf2ee19f0489c5a7
+Merge: ab16b24c eb1e6028
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Oct 1 10:22:06 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit aaaa65baa7fcfb65ae814528bdd93cc5c4ea540d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 16:59:48 2018 +0200
+
+    [khmer] Remove unused code
+
+ src/hb-ot-shape-complex-khmer.hh | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+commit eb1e60287732ede6040ce6f7498c10909448d248
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 15:31:50 2018 +0200
+
+    [test] Try import unicodedata2 as unicodedata
+
+ test/shaping/hb_test_tools.py | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 81afdbe803ca949d915d03cab4a6ed6c6e6ff304
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 15:01:04 2018 +0200
+
+    [use] Disable automatic ZWJ for 'akhn' feature
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/746
+
+ src/hb-ot-shape-complex-use.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ceef311dcaea7e1ecfedb4f1257a705572611f0f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 12:45:06 2018 +0200
+
+    [use] Change categories for Left_And_* matras
+
+    These are only relevant to Sinhala, because they decompose in other
+    cases.  The USE spec categorizes them all as VPst.  No idea why we
+    weren't following that before.
+
+ src/gen-use-table.py                 |  4 ++--
+ src/hb-ot-shape-complex-use-table.cc | 24 ++++++++++++------------
+ 2 files changed, 14 insertions(+), 14 deletions(-)
+
+commit 3426a361571a1996b5a895fb9374ce3a4a7f9af3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 12:55:57 2018 +0200
+
+    Unbreak bots
+
+ src/hb-cache.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 98ac01d3b3deb7c7f5411f6f25c6e7588d84b5f9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 12:10:00 2018 +0200
+
+    [morx] Break out if buffer gets into error
+
+    Was getting stuck not making progress somehow.
+
+ src/hb-aat-layout-common.hh     | 2 ++
+ src/hb-aat-layout-morx-table.hh | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+commit df827a6ab88cd8bde346176fc53a5c2d57eee808
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Oct 1 11:34:20 2018 +0200
+
+    [cache] Fix cache coherency corner-case
+
+    If key_bits+value_bits-cache_bits==32 then -1 is ambiguous...
+
+ src/hb-cache.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 0fa1edbd3bbf825be078677dc46c3440f9802551
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Oct 1 09:40:29 2018 +0330
+
+    [circleci] Couple of fixes (#1200)
+
+    * Raise error on warnings on -everything
+    * Enable fontconfig to two bots
+    * Fix msan bot now that all of its real complain are gone
+
+ .circleci/config.yml                    | 14 ++++++--------
+ src/check-symbols.sh                    |  2 ++
+ src/hb-ucdn.cc                          |  2 ++
+ test/fuzzing/run-shape-fuzzer-tests.py  |  2 ++
+ test/fuzzing/run-subset-fuzzer-tests.py |  2 ++
+ util/helper-cairo.cc                    |  2 ++
+ 6 files changed, 16 insertions(+), 8 deletions(-)
+
+commit 3babb0813c69d2b419f06773f366a44a9ad32cdb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 20:02:30 2018 +0200
+
+    [msan] Disable icu explicitly
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit dc9b47ae87096d34d146e50e44e742a76861976f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:35:12 2018 +0200
+
+    [msan] Remove uninstrumented libraries
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ad1c190ecfbac66ffeef69db769073a33331eed3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:26:45 2018 +0200
+
+    Correct fix for glib-mkenum warning
+
+ src/hb-buffer.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 1dd1e56bf42af5b11afc3e34f78869e93d39867e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:25:58 2018 +0200
+
+    Revert "Fix glib-mkenum warning"
+
+    This reverts commit 247756a7d89008ee6a7d1171dc07ba22454c6034.
+
+    Was wrong.  Right fix coming.
+
+ src/hb-buffer.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 3f08750fa6772e7e342b96192b84cb9963f7335b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:23:34 2018 +0200
+
+    Move _POSIX_SOURCE to hb.hh
+
+ src/hb-blob.cc | 5 -----
+ src/hb.hh      | 4 ++++
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+commit 90dd255e570bf8ea3436e2f29242068845256e55
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:19:54 2018 +0200
+
+    Change _HB_SCRIPT_MAX_VALUE from 0xFFFFFFFF to 0x7FFFFFFF
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/504
+
+ src/hb-common.h | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit dcfcb950b81a2865ef01f5a69087264b79ed1bfd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:14:50 2018 +0200
+
+    [test] Fix -Wunused-parameter warnings
+
+ test/api/hb-test.h          |  1 +
+ test/api/test-blob.c        |  2 +-
+ test/api/test-c.c           |  2 +-
+ test/api/test-font.c        | 16 ++++++++--------
+ test/api/test-multithread.c |  2 +-
+ test/api/test-ot-color.c    |  2 +-
+ test/api/test-shape.c       | 14 +++++++-------
+ test/api/test-unicode.c     | 10 +++++-----
+ 8 files changed, 25 insertions(+), 24 deletions(-)
+
+commit be0b2ed3162f465dbf44a0f018d4e2af5dcdf87c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 18:01:20 2018 +0200
+
+    More warning fixes
+
+ test/api/test-multithread.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 5c65ed800de4caef5ee9ad2111225fa5d8235737
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 17:48:55 2018 +0200
+
+    Fix bug introduced in 9b0b40b3c1ac8155c80ed5dc976228f4d3ec7e1f
+
+    Also discovered by msan bot.
+
+ src/hb-ot-shape-fallback.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 247756a7d89008ee6a7d1171dc07ba22454c6034
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 13:10:54 2018 +0200
+
+    Fix glib-mkenum warning
+
+      GEN      hb-gobject-enums.h
+    WARNING: Failed to parse "/*< private >*/" in ../../src/hb-buffer.h
+
+ src/hb-buffer.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 0a89f9572fe2d0d9fbf0297e0a69307f0ba1a17c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 17:44:15 2018 +0330
+
+    [circleci] Pass ‌freetype compile flags to right place
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ad701f05cc86c22e8e53b7f5458887457e3a5e5f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 17:30:42 2018 +0330
+
+    [circleci] Use an instrumented freetype on msan bot
+
+ .circleci/config.yml | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 57aabbc29ec6dfa7f1b57da7b6c62fdc547f8ef8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 16:31:28 2018 +0330
+
+    [circleci] Another on fixing msan
+
+ .circleci/config.yml | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 24f148df3ecc899c9cf6d5359d3d35ee5e84a98c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 14:46:56 2018 +0330
+
+    [circleci] minor
+
+ .circleci/config.yml | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 0a9aab672287149540e8d90b5063ad4c562c423c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 14:45:43 2018 +0330
+
+    [circleci] Try to fix msan bot
+
+ .circleci/config.yml | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit b5285b34798cb7ee672343d00cbe066ea8a2ef83
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 12:23:01 2018 +0200
+
+    [util] Remove unneeded virtual
+
+    clang warning:
+
+    ../../util/options.hh:72:13: warning: destination for this 'memset'
+    call is a pointer to dynamic class
+          'option_parser_t'; vtable pointer will be overwritten
+          [-Wdynamic-class-memaccess]
+        memset (this, 0, sizeof (*this));
+        ~~~~~~  ^
+    ../../util/options.hh:72:13: note: explicitly cast the pointer to
+    silence this warning
+        memset (this, 0, sizeof (*this));
+                ^
+                (void*)
+
+ util/options.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 89ed040b21b366c927199bedd0e4cb060389d076
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 06:06:26 2018 -0400
+
+    [util] Fix more non-virtual-destructor warnings
+
+ util/options.hh | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+commit 2382dd07fa6ff49638b146a523e9d2e93cf69ceb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:54:47 2018 -0400
+
+    Minor
+
+ util/options.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 9caa432d0c5c09c8151cfce1e2cc184fbdd89594
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:49:08 2018 -0400
+
+    [util] Use HB_FALLTHROUGH
+
+    Sure, gcc knows to warn about this as well:
+
+    ../../util/options.cc:175:17: warning: this statement may fall through
+    [-Wimplicit-fallthrough=]
+         case 1: m.r = m.t;
+                 ~~~~^~~~~
+    ../../util/options.cc:176:5: note: here
+         case 2: m.b = m.t;
+         ^~~~
+
+    But HOLY SMOKES, look at clang -Weverything bot message:
+
+    options.cc:176:5: warning: unannotated fall-through between switch
+    labels [-Wimplicit-fallthrough]
+        case 2: m.b = m.t;
+        ^
+    options.cc:176:5: note: insert 'HB_FALLTHROUGH;' to silence this
+    warning
+        case 2: m.b = m.t;
+        ^
+        HB_FALLTHROUGH;
+
+    Right, it's telling me to insert "HB_FALLTHROUGH;" there!!!!!!!!!
+
+ util/options.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 2e728a7d86c714d845524a0722c2b653feb9d915
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:47:36 2018 -0400
+
+    [util] Mark var static
+
+    From clang -Weverything bot:
+
+    options.cc:39:3: warning: no previous extern declaration
+    for non-static variable 'supported_font_funcs'
+    [-Wmissing-variable-declarations]
+
+ util/options.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e910a1aef4b2413c627240fc06d2a5696b24747a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:46:20 2018 -0400
+
+    [util] Add empty virtual destructor to option_group_t
+
+    From clang -Weverything bot:
+
+    ./options.hh:57:8: warning: 'option_group_t' has virtual functions
+    but non-virtual destructor [-Wnon-virtual-dtor]
+    struct option_group_t
+           ^
+
+ util/options.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit b1e07e1e6cc7a8e5445c7aeb9491ae629029011b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:43:22 2018 -0400
+
+    [indic/khmer] Remove use of global constructors
+
+    Alternative woul have been to resurrect F_COMBINE that I removed in
+    70136a78cb9eda244767f8e8a3d30d0f3c569d01
+
+    But this does it for now.  I'm not sure why check-static-inits.sh
+    didn't
+    catch this before.  Clang -Weverything bot did:
+
+      CXX      libharfbuzz_la-hb-ot-shape-complex-indic.lo
+    hb-ot-shape-complex-indic.cc:99:1: warning: declaration requires a
+    global constructor [-Wglobal-constructors]
+    indic_features[] =
+    ^
+    1 warning generated.
+      CXX      libharfbuzz_la-hb-ot-shape-complex-khmer.lo
+    hb-ot-shape-complex-khmer.cc:36:1: warning: declaration requires a
+    global constructor [-Wglobal-constructors]
+    khmer_features[] =
+    ^
+    1 warning generated.
+
+ src/hb-ot-map.hh                 |  2 ++
+ src/hb-ot-shape-complex-indic.cc | 34 +++++++++++++++++-----------------
+ src/hb-ot-shape-complex-khmer.cc | 18 +++++++++---------
+ 3 files changed, 28 insertions(+), 26 deletions(-)
+
+commit 00cd00e64130694ff7b49456d4bc421a153b4e6d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:34:30 2018 -0400
+
+    Tweak HB_TAG and HB_UNTAG
+
+    uint32_t was getting promoted to signed int, which is not what
+    we wanted...
+
+    Wow, clang has become good at generating warnings...
+
+    ../../src/hb-common.h:349:29: warning: signed shift result
+    (0xFF000000) sets the sign bit of the shift expression's type ('int')
+    and becomes negative [-Wshift-sign-overflow]
+      _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX, /*<
+      skip >*/
+                                                      ^~~~~~~~~~
+    ../../src/hb-common.h:93:20: note: expanded from macro 'HB_TAG_MAX'
+     define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
+                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ../../src/hb-common.h:89:57: note: expanded from macro 'HB_TAG'
+     define HB_TAG(c1,c2,c3,c4)
+     ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
+                                             ~~~~~~~~~~~~~~~^ ~~
+    ../../src/hb-common.h:349:3: warning: ISO C restricts enumerator
+    values to range of 'int' (4294967295 is too large) [-Wpedantic]
+      _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX, /*<
+      skip >*/
+      ^                                               ~~~~~~~~~~
+
+ src/hb-common.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8a31e406291f4cb27480fc85049f08abd739cb59
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 05:27:39 2018 -0400
+
+    [font] Make *_advance() fallback to *_advances
+
+    And remove redundant implementations.
+
+ src/hb-font.cc    | 12 ++++++++++++
+ src/hb-ft.cc      | 19 -------------------
+ src/hb-ot-font.cc | 22 ----------------------
+ 3 files changed, 12 insertions(+), 41 deletions(-)
+
+commit bd07d2878ff28baecf7b4b587a18ffbb744b7eb1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 03:54:40 2018 -0400
+
+    Use buffer scratch_flags to remember if we had any joiners
+
+ src/hb-buffer.hh                  |  3 ++-
+ src/hb-ot-layout.hh               | 12 ++++++++++--
+ src/hb-ot-shape-complex-arabic.cc |  3 +++
+ 3 files changed, 15 insertions(+), 3 deletions(-)
+
+commit ba0f0f156fe05bda760efcb0c8d34f303fa26ab0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 30 03:49:52 2018 -0400
+
+    Document setlocale() threadsafety issue
+
+    "Fixes" //github.com/harfbuzz/harfbuzz/issues/1191
+
+ src/hb-buffer.cc | 2 ++
+ src/hb-common.cc | 7 +++++++
+ 2 files changed, 9 insertions(+)
+
+commit 06be2aa93fa6ea8cc32684a4b51bfe927c5202bb
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Sep 30 00:15:25 2018 +0330
+
+    [ci] Build glib and freetype and enable msan bot (#1198)
+
+ .circleci/config.yml | 41 +++++++++++++++++++++--------------------
+ 1 file changed, 21 insertions(+), 20 deletions(-)
+
+commit cefdef0247026f941eba8930c73b66b0498bb63c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 29 10:19:54 2018 +0330
+
+    Minor on test-multithread, align the actual and expected results
+
+ test/api/test-multithread.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 678beff64ca3b2963de25d8a76a2bf3710c3d7a6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 29 10:16:14 2018 +0330
+
+    [circleci] Add -Wno-reserved-id-macro to clang-everything
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c763b9440189b541316054ba4f623e728b5aae77
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 20:53:07 2018 -0400
+
+    [test-multithread] Disable FreeType funcs
+
+ test/api/test-multithread.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 9b0b40b3c1ac8155c80ed5dc976228f4d3ec7e1f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 11:16:18 2018 -0400
+
+    Fix fallback kerning to check for current glyph's mask
+
+ src/hb-ot-shape-fallback.cc | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+commit 909a07b587884e9cd1d92ba9f3d5b96d8774c67a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 29 03:10:13 2018 +0330
+
+    [circleci] Improve clang-everything bot log, more to come
+
+    #1196
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9be8062b4d241f02bb96df436e98f10f08bda4f8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 29 02:11:05 2018 +0330
+
+    [ci] Another try on mingw bot
+
+ appveyor.yml | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit d4d261a97723b27fb9ad9a69b8dc7fd8c560a98b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 29 01:57:50 2018 +0330
+
+    [ci] Another try on fixing mingw bots
+
+    Per
+    https://github.com/Alexpux/MSYS2-packages/issues/163#issuecomment-73555971
+
+ appveyor.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7b68edf2abc7680199360d52ed283cfc4f49b7d5
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Sep 28 20:53:48 2018 +0330
+
+    [tests] Don't try to get glyph names on failures
+
+    As it may cause a race unrelated to the issue actually happened
+
+ test/api/test-multithread.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit d289d6381864649504abfb1196ac20a1d4664a4e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Sep 28 20:47:21 2018 +0330
+
+    [ci] Trying to fix mingw bot
+
+    As https://github.com/Alexpux/MSYS2-packages/issues/702
+
+ appveyor.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 33231a855f0e3d2a14e5e2fcb921c6fc773ae6cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 11:06:49 2018 -0400
+
+    Fix pthread fail for real
+
+    Using a hack...
+
+ test/api/Makefile.am | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 8cb8209c911a69442f23f744981e3ed01e44a3fc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 10:55:28 2018 -0400
+
+    Fix bot fails
+
+ test/api/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f4072e8cb81072cd6d51a2607efedb76c02e7db1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 10:14:23 2018 -0400
+
+    [morx] Remove mark_set from Insertion
+
+    text-rendering-tests test MORX-32 shows that for Insertion, an unset
+    mark is treated
+    as mark set at 0.  This is unlike the Reordering lookup where un
+    unset mark performs
+    nothing.
+
+    Fixes MORX-32.
+
+ src/hb-aat-layout-morx-table.hh | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit 0d18ec5467818fa8f763ec2871146a64d39987e7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 10:00:07 2018 -0400
+
+    [morx] unsafe-to-break in Insertion
+
+    Makes MORX-29, MORX-30, MORX-31 pass.
+
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 02bebe42c1ffbd8e11b232c943317c8cd8141afb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 09:51:35 2018 -0400
+
+    [test/text-rendering-tests] Update from upstream
+
+ test/shaping/data/text-rendering-tests/DISABLED          |   4 ++++
+ test/shaping/data/text-rendering-tests/Makefile.sources  |   4 ++++
+ .../text-rendering-tests/fonts/TestMORXThirtyone.ttf     | Bin 0 ->
+ 2964 bytes
+ .../text-rendering-tests/fonts/TestMORXThirtytwo.ttf     | Bin 0 ->
+ 2948 bytes
+ .../text-rendering-tests/fonts/TestMORXTwentynine.ttf    | Bin 0 ->
+ 3012 bytes
+ .../data/text-rendering-tests/tests/MORX-29.tests        |   4 ++++
+ .../data/text-rendering-tests/tests/MORX-30.tests        |   4 ++++
+ .../data/text-rendering-tests/tests/MORX-31.tests        |   8 ++++++++
+ .../data/text-rendering-tests/tests/MORX-32.tests        |   4 ++++
+ 9 files changed, 28 insertions(+)
+
+commit 4cd342baea323bf9709340bbabfc092c976c239c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 09:47:45 2018 -0400
+
+    Fix ubsan bot
+
+ test/api/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit b435df3a5b6f7fddc091c4362a36840305144a57
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 09:13:14 2018 -0400
+
+    More atomic tuneup
+
+ src/hb-atomic.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 7e6e094abd27fd022fe9aea1872ef82f6a0cdcec
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 08:45:57 2018 -0400
+
+    [test-multithread] Install ot funcs before filling ref buffer
+
+ test/api/test-multithread.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 21fbee831e0eab2c2f4513825c939158f4578156
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 08:43:37 2018 -0400
+
+    [test-multithread] Take num-threads and num-iters from command-line
+
+ test/api/test-multithread.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 598be3bb38fd11a288f8155b8c27ffef4ebdd8b9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 28 08:33:26 2018 -0400
+
+    Minor
+
+ test/api/test-multithread.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c09bf3d50589c8eb95b322ef3e4eb8a288dacebe
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Sep 28 16:13:01 2018 +0330
+
+    test-multithread, check the results on every iteration (#1194)
+
+ test/api/test-multithread.c | 59
+ ++++++++++++++++++++++++---------------------
+ 1 file changed, 32 insertions(+), 27 deletions(-)
+
+commit dbc3070a15290310bb5aade11d04eb24fe958094
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Fri Sep 28 16:01:15 2018 +0330
+
+    Make test-multithread pass the tsan bot test (#1193)
+
+ test/api/test-multithread.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit d2542cd28c70b2ba7ab28c0fe5459a1b4a873478
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 27 17:23:24 2018 -0400
+
+    More atomic fixup
+
+ src/hb-atomic.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3ee96984f4633852736b33640c89d1706bc77e0b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 27 17:20:26 2018 -0400
+
+    Fixup atomics from recent change
+
+ src/hb-atomic.hh | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 305468708dc9ce9dadad36c117c380f13bcc6a26
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 27 16:54:23 2018 -0400
+
+    [cache] Use atomic writes in clear()
+
+    To help TSan.
+
+ src/hb-cache.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 9e9a36ee651502b69717895385387951a2d0802a
+Author: Volker Krause <vkrause@kde.org>
+Date:   Thu Sep 27 16:33:49 2018 +0200
+
+    Fix infinite loop when walking up the directory hierarchy (#1183)
+
+    A single find_package(harfbuzz) line in user code resulted in
+    this loop
+    getting stuck when _harfbuzz_libdir_iter became "/".
+
+ src/harfbuzz-config.cmake.in | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 0c1d852bc41a4f69f890be4817c84bd7de56e07a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Sep 27 11:53:17 2018 +0330
+
+    Use clang for compiling freetype for tsan bot
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ab16b24cc94389ac66a9353327d2a87a7c230ed4
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 26 18:51:36 2018 -0700
+
+    tweaked get_fd fix
+
+ src/hb-ot-cff-common.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit dac70f252a84e1a255375eaacffc2cb3f3fc6e58
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 26 16:30:26 2018 -0700
+
+    Added CFF1 J font subset to api test
+
+    Also fixed FDSelect3_4::get_fd
+    Fixed test_subset_cff1_strip_hints (wrong font names!)
+
+ src/hb-ot-cff-common.hh                            |   2 +-
+ .../fonts/SourceHanSans-Regular.41,3041,4E9D.otf   | Bin 0 -> 5864 bytes
+ test/api/fonts/SourceHanSans-Regular.41,4E9D.otf   | Bin 0 -> 5500 bytes
+ test/api/test-subset-cff1.c                        |  25
+ +++++++++++++++++++--
+ 4 files changed, 24 insertions(+), 3 deletions(-)
+
+commit 662f7d7e8bfa77b21ffa05e853f61dda993dcc8a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 18:42:37 2018 -0400
+
+    [arabic] Do the joiner-flipping only for rlig feature
+
+    See comment.
+
+ src/hb-ot-shape-complex-arabic.cc | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+commit 7f30629cddcf0196d7b754df0cb2d4a8e5fed4b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 16:40:23 2018 -0400
+
+    [ft] Make TSan happy
+
+ src/hb-ft.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit ec743fce2a72a1cb76ac9401747a442a03a051d9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 16:37:18 2018 -0400
+
+    Add more atomic intrinsics
+
+ src/hb-atomic.hh | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+commit d183b33c1dd42055a9432f4a756ea20856913201
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 16:29:35 2018 -0400
+
+    Rename test
+
+ test/api/Makefile.am                                           | 2 +-
+ test/api/{test-subset-codepoints.c => test-collect-unicodes.c} | 0
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit c9c75fe3d9eb36f166d594ceb5889a1dc0b14fe6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Sep 27 00:08:06 2018 +0330
+
+    [ci] Compile freetype on tsan and put sanitizer flags on correct
+    places (#1188)
+
+ .circleci/config.yml | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+commit 39da1914b4fd1c58d61cb29c78a0904ff6b905c6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Sep 26 23:32:45 2018 +0330
+
+    Test freetype funcs on test-multithread (#1187)
+
+ test/api/Makefile.am        |  6 ++++--
+ test/api/test-multithread.c | 25 +++++++++++++++++--------
+ 2 files changed, 21 insertions(+), 10 deletions(-)
+
+commit e88009a93f5d13ed31b6262f928761e9574dcef1
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Sep 26 22:53:02 2018 +0330
+
+    Minor, remove the no longer needed comment on test-multithread
+
+ test/api/test-multithread.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 90a0f9fa0c020c268ac3ba31c7f1337eed85f35e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 15:03:07 2018 -0400
+
+    Make TSan happy with make_immutable()
+
+ src/hb-blob.cc    | 2 ++
+ src/hb-face.cc    | 2 ++
+ src/hb-font.cc    | 4 ++++
+ src/hb-unicode.cc | 2 ++
+ 4 files changed, 10 insertions(+)
+
+commit 34d5a2595331c568ae524057d031c9d5d2573978
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 15:02:21 2018 -0400
+
+    Fix test-multithread and increase num_threads to 30
+
+    What were you thinking? ;)
+
+ test/api/test-multithread.c | 56
+ +++++++++++++++++++++------------------------
+ 1 file changed, 26 insertions(+), 30 deletions(-)
+
+commit 8bb73dad7f3279e1f1362cf9a137504e8ef08985
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Sep 26 20:50:51 2018 +0330
+
+    Add a multithreaded test (#1184)
+
+ test/api/Makefile.am        |   6 ++
+ test/api/test-multithread.c | 146
+ ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 152 insertions(+)
+
+commit 04caf11608d2db13eb6ed2ecc3d406e284b4c13c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 26 12:13:47 2018 -0400
+
+    [hb-view] Change subpixel bits from 8 to 6
+
+    To match FreeType units, such that FreeType gets correct size from us.
+    This matters more now that we allow setting --ft-load-flags.
+
+ util/hb-view.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 824111d4842b9a7bbbdcd147325f8f372ed3d37c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 25 12:47:37 2018 -0400
+
+    Fix iOS build
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1179
+
+ src/hb-coretext.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4b4be7701f635f8378e7f868cfbe8d4571fc841f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Sep 25 09:24:35 2018 +0330
+
+    [circle] Add an obsessive clang bot (#1178)
+
+ .circleci/config.yml | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+commit ae7f0e83d4417fac2455c44eaea15b3cca03d18e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 24 22:49:44 2018 -0700
+
+    fixed memory leaks
+
+    in CFF1 & CFF2 accelerators, VORG subsetter
+
+ src/hb-ot-cff1-table.hh | 2 ++
+ src/hb-ot-cff2-table.hh | 2 ++
+ src/hb-ot-vorg-table.hh | 3 +++
+ 3 files changed, 7 insertions(+)
+
+commit 258b456566abd266657725b3fc4e70f18b370d5d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 24 16:50:47 2018 -0700
+
+    Added CFF1 & CFF2 api tests
+
+ test/api/Makefile.am                               |   4 +
+ test/api/fonts/AdobeVFPrototype.abc.otf            | Bin 0 -> 7800 bytes
+ test/api/fonts/AdobeVFPrototype.ac.nohints.otf     | Bin 0 -> 7152 bytes
+ test/api/fonts/AdobeVFPrototype.ac.otf             | Bin 0 -> 7336 bytes
+ test/api/fonts/SourceSansPro-Regular.abc.otf       | Bin 0 -> 3412 bytes
+ .../api/fonts/SourceSansPro-Regular.ac.nohints.otf | Bin 0 -> 3228 bytes
+ test/api/fonts/SourceSansPro-Regular.ac.otf        | Bin 0 -> 3332 bytes
+ test/api/test-subset-cff1.c                        | 104
+ +++++++++++++++++++++
+ test/api/test-subset-cff2.c                        | 104
+ +++++++++++++++++++++
+ 9 files changed, 212 insertions(+)
+
+commit 8282e881b51363811078bce53fad6aa5b41f7b41
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 19:43:01 2018 -0400
+
+    Disable msan bot again
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1175
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6c0e7eb6a6f3f888442c0a97ce6a771631990ed6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 19:07:23 2018 -0400
+
+    Minor
+
+ src/hb-ot-map.hh                 |  1 +
+ src/hb-ot-shape-complex-indic.cc | 34 +++++++++++++++++-----------------
+ src/hb-ot-shape-complex-khmer.cc | 18 +++++++++---------
+ 3 files changed, 27 insertions(+), 26 deletions(-)
+
+commit d748dc76644f28d4130f9cb1dee7a22cbe81c25d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 18:30:50 2018 -0400
+
+    More iter inits
+
+ src/hb-ot-layout-gsubgpos.hh | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit d9867497d09af929554eaa89cc6fee865b018646
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 18:11:59 2018 -0400
+
+    Minor
+
+ src/hb-ot-shape.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 70136a78cb9eda244767f8e8a3d30d0f3c569d01
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 18:03:34 2018 -0400
+
+    Remove F_COMBINE
+
+    Now I wonder if any bots will be unhappy we calling | in static
+    const initializations...
+    Or would that cost runtime init?  Our tests don't detect any..
+
+ src/hb-ot-map.hh                  | 2 --
+ src/hb-ot-shape-complex-arabic.cc | 2 +-
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+commit f048ead84a4d3fe0bb712ed228c2f39c01ce9705
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 18:01:53 2018 -0400
+
+    Some more
+
+ src/hb-ot-map.cc                   |  5 +++--
+ src/hb-ot-map.hh                   | 13 +++++++------
+ src/hb-ot-shape-complex-arabic.cc  | 18 +++++++++---------
+ src/hb-ot-shape-complex-hangul.cc  |  2 +-
+ src/hb-ot-shape-complex-indic.cc   |  8 ++++----
+ src/hb-ot-shape-complex-khmer.cc   |  8 ++++----
+ src/hb-ot-shape-complex-myanmar.cc | 10 +++++-----
+ src/hb-ot-shape-complex-tibetan.cc |  2 +-
+ src/hb-ot-shape-complex-use.cc     | 20 ++++++++++----------
+ src/hb-ot-shape.cc                 | 30 +++++++++++++++---------------
+ 10 files changed, 59 insertions(+), 57 deletions(-)
+
+commit 1676f608c8e4f880789252ca448bb008f6dd51b4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 17:55:03 2018 -0400
+
+    Minor refactoring
+
+ src/hb-ot-map.hh                   | 15 ++++++++++-
+ src/hb-ot-shape-complex-hangul.cc  |  2 +-
+ src/hb-ot-shape-complex-indic.cc   | 52
+ +++++++++++++++-----------------------
+ src/hb-ot-shape-complex-khmer.cc   | 38 ++++++++++------------------
+ src/hb-ot-shape-complex-myanmar.cc |  2 +-
+ 5 files changed, 51 insertions(+), 58 deletions(-)
+
+commit 10203339600e85d6aaffba6034ac250e72fdfc12
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Sep 25 01:00:32 2018 +0330
+
+    [circleci] Update sanitizer bots with newer clang and Ubuntu version
+    (#1176)
+
+ .circleci/config.yml | 48
+ ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 32 insertions(+), 16 deletions(-)
+
+commit 12b8baa7653741ba13a89cd40f1f36b8bac11666
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 17:22:39 2018 -0400
+
+    [msan] Enable again to get a build log, and try to play with
+    suppressions
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit aec0d3cbc923a8801c5bd9e9ae05801a31a7260c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 13:12:15 2018 -0400
+
+    [ubsan] Re-enable now that it passes locally
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4839807340cc73d5ba826dff4b4ba358775a213d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 13:11:34 2018 -0400
+
+    [check-static-inits.sh] Allow some if ubsan is in effect
+
+ src/check-static-inits.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0604bf2b3846b200c56447ffe542bf69c0529a06
+Merge: 76e54d2b 45f5aa97
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 24 10:09:25 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit e45ba31dc723988150ef766758fa89fecd50ca03
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 13:04:48 2018 -0400
+
+    [check-symbols.sh] Allow weak objects "V"
+
+    ubsan generates these.
+
+ src/check-symbols.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d07f3111b4bc38798e16a2459b80a16d7a9f9ff1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 13:01:35 2018 -0400
+
+    Link API test programs with C++ linker
+
+    Needed to make ubsan work.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1174
+
+ test/api/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit a96508cfc9bd9013d24b18547fcd9c03e08fe2f2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 12:52:42 2018 -0400
+
+    [msan] Add MSAN_OPTIONS=exitcode=42
+
+    Default exit value is 77, which causes autotools to "skip" test.
+
+ .circleci/config.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 45f5aa97905996e3486c6dbba8493b11cfa0cf15
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 12:43:29 2018 -0400
+
+    [circleci] Disable msan and ubsan builds
+
+    https://github.com/harfbuzz/harfbuzz/issues/1174
+    https://github.com/harfbuzz/harfbuzz/issues/1175
+
+ .circleci/config.yml | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 2d93148a0f915bb52433ecc9d66845191a2f9135
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 11:52:22 2018 -0400
+
+    Ignore weak symbols in check-symbols.sh
+
+    Some clang versions leave a std::round(float) weak symbol around...
+
+ src/check-symbols.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 55bae6825ed2058255a512a73293e3cdff0e78a4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 10:43:06 2018 -0400
+
+    [docs] A few improvements
+
+    If we wrote just this much every day...
+
+ src/hb-buffer.cc |  4 ++++
+ src/hb-buffer.h  | 20 +++++++++++++++-----
+ src/hb-face.cc   | 11 +++++++----
+ src/hb-font.cc   | 12 +++++++-----
+ 4 files changed, 33 insertions(+), 14 deletions(-)
+
+commit 57fa2c23de8b6b66894d6872d192ac90ec8bf05a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 09:57:52 2018 -0400
+
+    Readjust Hebrew composition again
+
+ src/hb-ot-shape-complex-hebrew.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7f335390f3a498119319a0e6c3ce7656a3902066
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 09:56:18 2018 -0400
+
+    Revert change that would decompose text if GPOS mark feature is
+    available
+
+    https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920
+
+ src/hb-ot-shape-normalize.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit a6f4b2f7cd088aeb44e1aac672434641f4f9e484
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 24 09:54:37 2018 -0400
+
+    Fix normalization
+
+    https://github.com/harfbuzz/harfbuzz/commit/62d1e0852a5549a1b510ad46a4b89f12730bb708#commitcomment-30613091
+
+ src/hb-ot-shape-normalize.cc | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 3583fb03b14a10ec5ab5f9c480e150934101fd0b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 23 22:33:38 2018 -0400
+
+    Simplify ZWJ-skipping a bit
+
+    Towards disabling ZWJ-skipping in certain GPOS contexts.
+
+    Part of https://github.com/flutter/flutter/issues/16886
+
+ src/hb-ot-layout-gsubgpos.hh       |  6 +++---
+ src/hb-ot-shape-complex-indic.cc   | 21 ++++++++++++++++-----
+ src/hb-ot-shape-complex-khmer.cc   | 21 ++++++++++++++-------
+ src/hb-ot-shape-complex-myanmar.cc | 15 ++++++++++++++-
+ src/hb-ot-shape-complex-use.cc     | 15 +++++++++++++--
+ 5 files changed, 60 insertions(+), 18 deletions(-)
+
+commit 9516cbd3df7ccdb40b27a7ba99a1e0da8a6b170c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 23 22:00:34 2018 -0400
+
+    Reinit skippy iters when auto_zwj / auto_zwnj change
+
+    Ouch.  How did we not hit this bug before...
+
+ src/hb-ot-layout-gsubgpos.hh | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+commit 62d1e0852a5549a1b510ad46a4b89f12730bb708
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 23 21:32:18 2018 -0400
+
+    Prefer decomposed form if font has GPOS mark feature
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/653
+
+ src/hb-ot-shape-complex-hebrew.cc |   2 +-
+ src/hb-ot-shape-normalize.cc      | 126
+ ++++++++++++++++++++------------------
+ src/hb-ot-shape-normalize.hh      |   7 ++-
+ 3 files changed, 72 insertions(+), 63 deletions(-)
+
+commit d7f21777e6a797758ab234555f5f7e07c87278f9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 23 19:12:52 2018 -0400
+
+    [ot-font] Fix leak
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1171
+
+    I'm glad we have leak-detector bots now.
+
+ src/hb-ot-post-table.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit ae39a53f55e6b812defb4c7b48562651c9eb13a3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 22 14:22:17 2018 +0330
+
+    Add bots with address- and thread-sanitizer
+
+ .circleci/config.yml | 52
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+commit 24dd6c1a9d8d571c30dce4d39c1975b1d1cedc2a
+Author: Matt Oliver <protogonoi@gmail.com>
+Date:   Sun Sep 23 18:08:30 2018 +1000
+
+    src/hb-blob.cc: Fix mmap functionality with UWP.
+
+ src/hb-blob.cc | 27 +++++++++++++++++++++++++++
+ src/hb.hh      |  4 +++-
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+commit b7f1bbc2f8b14a402fa9e42e88919dc0173373ce
+Author: Khaled Hosny <khaledhosny@eglug.org>
+Date:   Sat Sep 22 16:41:56 2018 +0200
+
+    [test] Fix printing subprocess error messages
+
+    Decode the string as Python 3 returns bytes string, and also don’t
+    assume that it ends with a new line.
+
+ test/shaping/run-tests.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 403019482b0d7f17fbdb5def2be5f43e28bafcf3
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 22 17:24:03 2018 +0330
+
+    Fix test-subset-* leak issues
+
+    See also https://github.com/harfbuzz/harfbuzz/pull/1169
+
+ test/api/hb-subset-test.h | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+commit f6ebe1f4dc95a7c4b3a0af23086873a11867c1d9
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 22 17:05:52 2018 +0330
+
+    Fix test-ot-math leak issue
+
+    See also https://github.com/harfbuzz/harfbuzz/pull/1169
+
+ test/api/test-ot-math.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 669ac81ac52e9d559324db851a9ee46ef651e7b0
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 22 16:49:23 2018 +0330
+
+    Fix test-set leak issue
+
+    See also https://github.com/harfbuzz/harfbuzz/pull/1169
+
+ test/api/test-set.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit ef9307fd2227bf0f750d8f7fafae466affc81454
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Sep 22 16:45:31 2018 +0330
+
+    Fix test-font leak issue
+
+    See also https://github.com/harfbuzz/harfbuzz/pull/1169
+
+ test/api/test-font.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 76e54d2bd804414183858ca198157050419dfe6c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Sep 21 12:16:36 2018 -0700
+
+    fixed subroutinized CFF2 flattening
+
+    and some code cleanup
+
+ src/hb-cff-interp-common.hh    |  2 +-
+ src/hb-cff-interp-cs-common.hh | 13 -------------
+ src/hb-cff2-interp-cs.hh       |  7 ++++---
+ 3 files changed, 5 insertions(+), 17 deletions(-)
+
+commit 321e592333014f713557e8ce8041dcb5de710218
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 20 10:31:06 2018 -0700
+
+    Added desubroutinize option to generate-expected-outputs.py
+
+    Currently hb-subset always desubroutinizes CFF fonts.
+    Note that even with this option fonttools won't generate the expected
+    subset CFF fonts. They were manually created & tweaked to match
+    hb-subset output.
+
+ test/subset/generate-expected-outputs.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit f212c050ad50898d5105d1d3a6ea3498f94ee462
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 20 09:45:43 2018 -0700
+
+    Added VORG struct and its subsetter
+
+    new file: hb-ot-vorg-table.hh
+
+ src/Makefile.sources    |   1 +
+ src/hb-ot-vorg-table.hh | 163
+ ++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-subset.cc        |   5 +-
+ 3 files changed, 168 insertions(+), 1 deletion(-)
+
+commit 5fd8bce945e7efaa48d0c29eb8b2700027bd3c0b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 22:34:09 2018 -0400
+
+    [morx] Fix mark_set check
+
+ src/hb-aat-layout-morx-table.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 1377adc8a88c627891cb8b9cea511d8f9f5324f9
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 19 17:00:10 2018 -0700
+
+    Added SourceHanSans-Regular for CFF subset test
+
+    Disabled FDSelect serialization to format 0 for compatibility with
+    fonttools
+
+ src/hb-subset-cff-common.cc                          |  16
+ +++++++++++++---
+ .../japanese/SourceHanSans-Regular.default..otf      | Bin 0 ->
+ 2340 bytes
+ ...Regular.default.3042,3044,3046,3048,304A,304B.otf | Bin 0 ->
+ 6248 bytes
+ ...Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 0 ->
+ 6432 bytes
+ .../SourceHanSans-Regular.default.61,63,65,6B.otf    | Bin 0 ->
+ 5428 bytes
+ ...Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 0 ->
+ 6552 bytes
+ .../japanese/SourceHanSans-Regular.default.660E.otf  | Bin 0 ->
+ 5196 bytes
+ .../japanese/SourceHanSans-Regular.drop-hints..otf   | Bin 0 ->
+ 2188 bytes
+ ...ular.drop-hints.3042,3044,3046,3048,304A,304B.otf | Bin 0 ->
+ 6076 bytes
+ ...ular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 0 ->
+ 6180 bytes
+ .../SourceHanSans-Regular.drop-hints.61,63,65,6B.otf | Bin 0 ->
+ 5312 bytes
+ ...ular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 0 ->
+ 6248 bytes
+ .../SourceHanSans-Regular.drop-hints.660E.otf        | Bin 0 ->
+ 5088 bytes
+ test/subset/data/fonts/SourceHanSans-Regular.otf     | Bin 0 ->
+ 16427580 bytes
+ test/subset/data/tests/japanese.tests                |   1 +
+ 15 files changed, 14 insertions(+), 3 deletions(-)
+
+commit 0739b28169eb63332b31420deb5bf58b5446f154
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 17:32:21 2018 -0400
+
+    [aat] Minor
+
+ src/hb-aat-layout-common.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7671cb9b04770d50b1b2a05a24f6fadc35993cd1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 17:10:26 2018 -0400
+
+    [coretext] Minor
+
+ src/hb-coretext.cc | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit dc8ed45292ce4e522c3bda03fd83873da7b6591e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 16:46:41 2018 -0400
+
+    [morx] Implement forward/backward processing
+
+    We reverse too many times. Can be optimized. But I doubt many fonts
+    use reverse lookups, so doesn't matter.
+
+    Other than not applying user features, this completes morx table
+    implementation.
+
+ src/hb-aat-layout-morx-table.hh | 40
+ ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+commit 3bccd62196b5dff70d446c3fe053b1b47bb9c19e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 16:24:34 2018 -0400
+
+    [morx] Implement horiz-only/vert-only subtables
+
+ src/hb-aat-layout-morx-table.hh | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+commit 041a08de3d0ca74d3e2fdccfa5311ff26a8b97e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 19 16:02:56 2018 -0400
+
+    [morx] Improve buffer position in Insertion w DontAdvance and wo
+
+    Just speculation. Needs tests to determine which is correct behavior.
+
+ src/hb-aat-layout-morx-table.hh | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+commit ebeccf3e63bff96b7a7766dea566704a9cbeae44
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 18 17:24:30 2018 -0700
+
+    fixed char widths & standard Encoding in subset CFF
+
+    also merged flush_n_args to flush_args into one
+    takes start index of the arguments on stack instead of count
+
+ src/hb-cff-interp-cs-common.hh | 20 +++++---------------
+ src/hb-cff1-interp-cs.hh       | 11 +++++++----
+ src/hb-cff2-interp-cs.hh       |  2 +-
+ src/hb-subset-cff1.cc          | 22 ++++++++++++++++------
+ src/hb-subset-cff2.cc          | 12 ++++++------
+ 5 files changed, 35 insertions(+), 32 deletions(-)
+
+commit bf4eb2e4cf8d08b674f81954e22b331cca2b3721
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 18 15:53:37 2018 -0700
+
+    Added SourceSansPro-Regular along as CFF full-font test case
+
+    derived "expected" subset fonts from fonttools then manually tweaked
+    further so they resemble hb-subset output
+
+ ...ourceSansPro-Regular.default.1FC,21,41,20,62,63.otf | Bin 0 ->
+ 3640 bytes
+ .../SourceSansPro-Regular.default.61,62,63.otf         | Bin 0 ->
+ 3400 bytes
+ .../SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf   | Bin 0 ->
+ 3596 bytes
+ ...ceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf | Bin 0 ->
+ 3480 bytes
+ .../SourceSansPro-Regular.drop-hints.61,62,63.otf      | Bin 0 ->
+ 3276 bytes
+ ...SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf | Bin 0 ->
+ 3448 bytes
+ test/subset/data/fonts/SourceSansPro-Regular.otf       | Bin 0 ->
+ 220852 bytes
+ test/subset/data/tests/full-font.tests                 |   1 +
+ test/subset/run-tests.py                               |   4 ++--
+ test/subset/subset_test_suite.py                       |   5 +++++
+ 10 files changed, 8 insertions(+), 2 deletions(-)
+
+commit e75e7224c9c02ab99e132a51fe8801e29827cac5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 15:34:39 2018 -0700
+
+    include curve control points in extents
+
+    this makes results consistent with FT
+    also optimized handling of path end points
+
+ src/hb-cff-interp-cs-common.hh |  6 +++---
+ src/hb-ot-cff1-table.cc        | 27 +++++++++++++++++++++++++--
+ 2 files changed, 28 insertions(+), 5 deletions(-)
+
+commit 98b94f8ba53276887ab583eeeb4cb097c7b84b2c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 13:56:39 2018 -0700
+
+    fix static_assert failure in OffsetTo<TopDict>
+
+ src/hb-ot-cff2-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d050ab8d3e73debfb414fc8c9426180459150b61
+Merge: f0a4e0c2 388ab916
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 13:07:29 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit f0a4e0c2ca5ee0225765590384216d5d5367de7e
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 12:11:56 2018 -0700
+
+    fix build attempt ^3
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f0d74971aee5ce309bdfa2a4397667f14ee15f42
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 12:02:12 2018 -0700
+
+    fix attempt ^2: unuse INT32_MAX/MIN
+
+ src/hb-ot-cff1-table.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 4d963a2711e6035e97e246241d8420273363f857
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 11:28:33 2018 -0700
+
+    fix build attempt
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 388ab91642734e1ba0d7a4a4f29a17b15f1b249d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 17 19:29:34 2018 +0200
+
+    [morx] Implement InsertionChain
+
+ src/hb-aat-layout-morx-table.hh | 87
+ ++++++++++++++++-------------------------
+ 1 file changed, 33 insertions(+), 54 deletions(-)
+
+commit c0c85b852d37dad75eeef473e6dd3ec91a3b559b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 17 11:14:56 2018 -0700
+
+    implemented get_glyph_extents with CFF1
+
+    Implemented path operators in a new struct PathProc hooked up
+    to CSOpSet
+    Added current point to CSInterpEnv
+
+ src/hb-cff-interp-common.hh    |  86 ++++++++-
+ src/hb-cff-interp-cs-common.hh | 425
+ +++++++++++++++++++++++++++++++++++++++--
+ src/hb-cff1-interp-cs.hh       |  18 +-
+ src/hb-cff2-interp-cs.hh       |  10 +-
+ src/hb-null.hh                 |   2 +-
+ src/hb-ot-cff1-table.cc        |  82 ++++++++
+ src/hb-ot-cff1-table.hh        |  95 +++++----
+ src/hb-ot-face.cc              |   1 +
+ src/hb-ot-face.hh              |   1 +
+ src/hb-ot-font.cc              |   2 +
+ src/hb-subset-cff1.cc          |   4 +-
+ src/hb-subset-cff2.cc          |  10 +-
+ 12 files changed, 657 insertions(+), 79 deletions(-)
+
+commit d8d1e7df0057c79f54d855b7bfec2d21f59b09e8
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Mon Sep 17 11:09:51 2018 -0400
+
+    Don't enforce a native direction for Old Hungarian
+
+ src/hb-common.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6a97d0f3d377a35ea691d15ac142ce043f953e71
+Author: Simon Hausmann <hausmann@gmail.com>
+Date:   Mon Sep 17 10:33:34 2018 +0200
+
+    Fix installation of cmake config when building with cmake (#1161)
+
+    When building with the auto tools, the manually mantained
+    harfbuzz-config.cmake is installed. When building with cmake, we
+    can use
+    cmake to generate the correct config files for us and install them.
+
+ CMakeLists.txt | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+commit 606bf57430370810f7bb62ba12b9685d8943685d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 19:33:48 2018 +0200
+
+    Revert forcing use of single-parameter static_assert()
+
+    Some clang versions define static_assert as a macro apparently,
+    so we cannot
+    redefine it...
+
+    This reverts commit 94bfea0ce6a7b4d5641c198d50751748a353df11.
+    This reverts commit 4e62627831e7457ed60ff87712570065b14b200a.
+
+ src/hb-atomic.hh                           |  4 ++--
+ src/hb-buffer.cc                           |  2 +-
+ src/hb-buffer.hh                           |  4 ++--
+ src/hb-cache.hh                            |  4 ++--
+ src/hb-coretext.cc                         |  2 +-
+ src/hb-debug.hh                            |  2 +-
+ src/hb-dsalgs.hh                           |  4 ++--
+ src/hb-machinery.hh                        |  4 ++--
+ src/hb-null.hh                             |  8 +++----
+ src/hb-open-type.hh                        |  4 ++--
+ src/hb-ot-layout-common.hh                 |  2 +-
+ src/hb-ot-layout-gdef-table.hh             |  6 +++---
+ src/hb-ot-layout.cc                        | 14 ++++++------
+ src/hb-ot-map.cc                           |  2 +-
+ src/hb-ot-math-table.hh                    |  2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ src/hb-ot-shape-complex-indic.hh           |  2 +-
+ src/hb-ot-shape-complex-use.cc             |  2 +-
+ src/hb-set-digest.hh                       |  4 ++--
+ src/hb-set.hh                              |  6 +++---
+ src/hb-uniscribe.cc                        |  2 +-
+ src/hb.hh                                  | 34
+ +++++++++++++-----------------
+ util/options.cc                            |  3 ++-
+ 23 files changed, 58 insertions(+), 61 deletions(-)
+
+commit cbcaba6ffdf6b147d45baa95d62fd29cec67ed54
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 19:25:19 2018 +0200
+
+    One more bot fix
+
+ src/hb-unicode.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 94bfea0ce6a7b4d5641c198d50751748a353df11
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 19:12:19 2018 +0200
+
+    Fix build, another try
+
+ util/options.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 89dd4b959773d35981299551074ccc7a1eb332bd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 18:11:46 2018 +0200
+
+    Fix bots
+
+    "Unused private member" warning turned error.  ugh.
+
+ src/hb-aat-layout-morx-table.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 4e62627831e7457ed60ff87712570065b14b200a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 18:09:36 2018 +0200
+
+    Enforce single-param static_assert() only
+
+    So we don't accidentally break it again.
+
+ src/hb-atomic.hh                           |  4 ++--
+ src/hb-buffer.cc                           |  2 +-
+ src/hb-buffer.hh                           |  4 ++--
+ src/hb-cache.hh                            |  4 ++--
+ src/hb-coretext.cc                         |  2 +-
+ src/hb-debug.hh                            |  2 +-
+ src/hb-dsalgs.hh                           |  4 ++--
+ src/hb-machinery.hh                        |  4 ++--
+ src/hb-null.hh                             |  8 +++----
+ src/hb-open-type.hh                        |  4 ++--
+ src/hb-ot-layout-common.hh                 |  2 +-
+ src/hb-ot-layout-gdef-table.hh             |  6 +++---
+ src/hb-ot-layout.cc                        | 14 ++++++------
+ src/hb-ot-map.cc                           |  2 +-
+ src/hb-ot-math-table.hh                    |  2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh |  2 +-
+ src/hb-ot-shape-complex-indic.hh           |  2 +-
+ src/hb-ot-shape-complex-use.cc             |  2 +-
+ src/hb-set-digest.hh                       |  4 ++--
+ src/hb-set.hh                              |  6 +++---
+ src/hb-uniscribe.cc                        |  2 +-
+ src/hb.hh                                  | 34
+ +++++++++++++++++-------------
+ 22 files changed, 60 insertions(+), 56 deletions(-)
+
+commit f1a86e1e6f3906f33fc89de694a4bbbc3e40d2bc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 18:01:32 2018 +0200
+
+    Remove unused try
+
+ src/hb-null.hh | 13 -------------
+ 1 file changed, 13 deletions(-)
+
+commit ebd50b3c83a22a0fdba53271275b8619a23739aa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 16 17:57:12 2018 +0200
+
+    Fix static_assert
+
+ src/hb-open-type.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 10642b3fbfbc1776e784b190c43a9e0693dd423a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Sep 15 19:43:33 2018 +0200
+
+    Disallow null-enabled offsets to unsized structures...
+
+    ...like UnsizedArrayOf<>.
+
+    This fixes a class of crasher bugs, mostly with color and AAT tables.
+    We
+    cannot use nullable offsets to varsized data that does not declare
+    min_size,
+    because it's nost safe to use our fixed-size null pool for types
+    that have
+    their size external.  So, use non_null'able offsets for these.
+
+    A further enhancement would be to make use of min_size in Null<>
+    itself.
+    Will try that after.
+
+ src/hb-aat-layout-common.hh     |  8 ++++----
+ src/hb-aat-layout-feat-table.hh |  2 +-
+ src/hb-aat-layout-morx-table.hh | 10 +++++-----
+ src/hb-aat-layout-trak-table.hh |  4 ++--
+ src/hb-aat-ltag-table.hh        |  2 +-
+ src/hb-open-type.hh             |  5 +++++
+ src/hb-ot-color-cbdt-table.hh   |  4 +---
+ src/hb-ot-color-colr-table.hh   |  4 ++--
+ src/hb-ot-color-cpal-table.hh   |  8 ++++----
+ src/hb-ot-color-svg-table.hh    |  2 +-
+ src/hb-ot-layout-common.hh      | 18 ++++++++++--------
+ src/hb-ot-layout-jstf-table.hh  |  4 ++--
+ 12 files changed, 38 insertions(+), 33 deletions(-)
+
+commit 9ff76c6025b55d184c96b193f23aa935ab32f1fc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Sep 15 18:31:14 2018 +0200
+
+    [morx] Respect default feature settings
+
+    Does NOT apply user-selected features.  But at least now enables
+    correct subtables.
+
+ src/hb-aat-layout-morx-table.hh | 34 +++++++++++++++++++++++-----------
+ 1 file changed, 23 insertions(+), 11 deletions(-)
+
+commit 2f97da6e2d6629e112789d399765d90f96952c0a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Sep 15 14:51:50 2018 +0200
+
+    [aat] Change version field
+
+ src/hb-aat-layout-morx-table.hh | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+commit 29c2bd1795b933a611512af50a14f25e25d43159
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Sep 15 14:47:18 2018 +0200
+
+    [morx] Add stub for InsertionChain
+
+ src/hb-aat-layout-morx-table.hh | 209
+ ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 200 insertions(+), 9 deletions(-)
+
+commit f8ccb545c47abe8f0f4ed318ff7b5bf176913893
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 18:59:53 2018 +0200
+
+    [dfont] Disable null-processsing for offsets
+
+    An offset to unsized arrayis not safe to be redirected to our
+    fixed-sized
+    null pool.  Plus, we want to reject, not repair, bad-looking dfonts.
+
+ src/hb-open-file.hh | 8 ++++----
+ src/hb-open-type.hh | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 01b9148d9ae7d18228538774243e49840cfd2499
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 14:23:09 2018 +0200
+
+    [unicode] Move Fitzpatrick hack from ot-layout into unicode.hh
+
+ src/hb-ot-layout.hh | 12 +-----------
+ src/hb-unicode.hh   | 36 +++++++++++++++++++++++++++---------
+ 2 files changed, 28 insertions(+), 20 deletions(-)
+
+commit 6ebbf514ac90712fe089b2b64f68d1cf681edd5d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 12:15:53 2018 +0200
+
+    Minor
+
+ src/hb-ot-layout.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 957dbed388fc3214248f6aca65902ad277d070fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 12:14:42 2018 +0200
+
+    Fix builds
+
+ src/hb-aat-layout-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4653e6cf3c1ef5005886d901df30e952d57eed6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 11:31:33 2018 +0200
+
+    [aat] Add enums for pre-defined state and classes
+
+    Not sure how I didn't add before...
+
+ src/hb-aat-layout-common.hh | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+commit 67449c39331babb88f7d29d737895d786cd5da33
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 14 10:58:00 2018 +0200
+
+    Don't dereference offset before check_struct()
+
+ src/hb-open-file.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit f2c4720ae696096d90493db218ef1283681561e7
+Merge: 1234a813 ca746f26
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 13 12:44:00 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit ca746f261e1e54cec2f9c8bc7a6f930491e19418
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 20:35:21 2018 +0200
+
+    [dfont] Also check dataLen range in sanitize
+
+    Just to disagree with myself re being done with this code...
+
+ src/hb-open-file.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 3789c557ca06aef430726f4942cafecac6fe4eef
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 20:30:04 2018 +0200
+
+    [dfont] Solve the mystery +2 offset thing!
+
+    Previously, ResourceForkHeader was defined as 30 bytes, having the
+    typeCountM1 as last member.
+    There was a mysterious offset-by-2 in the code, derived from FontTools
+    and JDK code this was
+    ported from.
+
+    In testing, I observed that typeListZ offset is actually 28.
+    Suggesting that the typeCountM1
+    does NOT actually belong to ResourceForkHeader, but belongs to the
+    array itself.  Adjusting for
+    that resolves the mystery +2 offset hack, so everything is clean
+    and good now.
+
+    This, concludes my dfont hacking.  The code looks great now, and
+    I'm happy to leave it.
+    Fuzzers might disagree though, we will see!
+
+ src/hb-open-file.hh | 30 ++++++++++++------------------
+ src/hb-open-type.hh | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 56 insertions(+), 18 deletions(-)
+
+commit effc7ced72a6ce0fea328a8b68dc3d55f09774f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 20:21:54 2018 +0200
+
+    Rename HeadlessArrayOf::len to lenP1
+
+    So it doesn't accidentally match our templates, etc.
+
+ src/hb-open-type.hh            | 14 +++++++-------
+ src/hb-ot-layout-gsub-table.hh | 10 +++++-----
+ src/hb-ot-layout-gsubgpos.hh   | 10 +++++-----
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+commit 1234a8136891429bb7353f47480595f44615f322
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 13 10:55:56 2018 -0700
+
+    add head table to CFF/CFF2
+
+ src/hb-ot-cff1-table.hh | 4 ++++
+ src/hb-ot-cff2-table.hh | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+commit 180a88a96ce327e4103df3635c73559de65d1546
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 19:19:57 2018 +0200
+
+    [dfont] Some more
+
+ src/hb-open-file.hh | 21 ++++++++-------------
+ 1 file changed, 8 insertions(+), 13 deletions(-)
+
+commit 0ab0f1e5ac5ccb07c57364e9f5be0b991398eb6f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 19:13:01 2018 +0200
+
+    [dfont] Push methods further down
+
+ src/hb-open-file.hh | 58
+ ++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+commit 8c9bdcc1feeab321a642bdaac50b716e48ce4263
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 19:08:22 2018 +0200
+
+    [dfont] Minor
+
+ src/hb-open-file.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 4479d3a2eda57d278700f5c78414ef6ef617d2a9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 19:05:59 2018 +0200
+
+    [dfon]t Sanitize OpenTypeFontFace
+
+ src/hb-dsalgs.hh    |  6 ------
+ src/hb-open-file.hh | 21 +++++++++------------
+ 2 files changed, 9 insertions(+), 18 deletions(-)
+
+commit 3fba41906fba28c5ea01cc0749654de862453bf4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 18:49:16 2018 +0200
+
+    [dfont] Minor
+
+ src/hb-open-file.hh | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+commit bf852f0e62a8bdbb809af6a975f8ae8eed708d70
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 18:47:53 2018 +0200
+
+    [dfont] Make test pass
+
+    Offset 0 is not null in this context.
+
+ src/hb-open-file.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 29faebe911a13916aa3d737e93d38deedc53567f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 18:45:35 2018 +0200
+
+    Allow Offset<>'s that have no 0==null
+
+ src/hb-open-type.hh | 43 +++++++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 22 deletions(-)
+
+commit 82f4d776c21b7c1224dd7073ce69cdf76d85f16b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 18:27:20 2018 +0200
+
+    [dfont] Minor
+
+ src/hb-open-file.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 07e0ca930c29757217c2f9e4e0e6954657b6b82d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 17:39:09 2018 +0200
+
+    [bytes] Rename content to arrayZ
+
+ src/hb-dsalgs.hh        | 16 ++++++++--------
+ src/hb-ot-post-table.hh |  2 +-
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+commit dbb764dceb61365b7360a48d581ba5a4b3526e98
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 16:49:26 2018 +0200
+
+    [dfont] Clean up sanitize()
+
+    I don't think I broke anything.  Fuzzers will let me know..
+
+ src/hb-dsalgs.hh    |   8 ++++
+ src/hb-open-file.hh | 122
+ ++++++++++++++++++++++++----------------------------
+ 2 files changed, 64 insertions(+), 66 deletions(-)
+
+commit 361fc2686152ad8c0ebaf19e0522e0fc58ba3953
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 16:47:33 2018 +0200
+
+    Fix OffsetTo::sanitize() after reshuffling
+
+ src/hb-open-type.hh | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+commit 4c6b0fb5f6668a6e562260d16f629ad3c41e8961
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 16:39:30 2018 +0200
+
+    OffsetTo::sanitize() Add version with three user_data
+
+ src/hb-open-type.hh | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+commit a73bea69c599787b4cfeac92a3afd00749e00434
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 16:31:31 2018 +0200
+
+    OffsetTo::sanitize() more shuffling
+
+ src/hb-open-type.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit b482e5231cd5987082dd2c05fd649c3653f3c67a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Sep 13 16:29:49 2018 +0200
+
+    OffsetTo::sanitize() reshuffling
+
+ src/hb-open-type.hh | 26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+commit 3cae9c75153277b9cfaaba20e0de84e420aeb1eb
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 12 17:23:08 2018 -0700
+
+    fixed hb_plan_subset_cff_fdselect
+
+    FDSelect3/4 sentinel size wasn't taken into account
+
+ src/hb-subset-cff-common.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 0f159a38a62bbf1b7fb267694a5d91d8135da625
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 12 16:08:54 2018 -0700
+
+    fixed serialize_fdselect_3_4
+
+ src/hb-ot-cff-common.hh     |  6 ++++
+ src/hb-ot-cff1-table.hh     |  6 ----
+ src/hb-subset-cff-common.cc | 68
+ ++++++++++++++++++++++++++-------------------
+ src/hb-subset-cff-common.hh | 10 +++----
+ src/hb-subset-cff1.cc       | 12 ++++----
+ src/hb-subset-cff2.cc       | 12 ++++----
+ 6 files changed, 63 insertions(+), 51 deletions(-)
+
+commit 1608481d88919ca748e367146e3a78458d5bbe8f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Sep 12 13:22:19 2018 -0700
+
+    fixed bugs in Charset serialization
+
+    also some code cleanup
+
+ src/hb-ot-cff1-table.hh |  4 ++--
+ src/hb-subset-cff1.cc   | 44 ++++++++++++++++++++------------------------
+ 2 files changed, 22 insertions(+), 26 deletions(-)
+
+commit f45ac6296add6435ea5a902f7519187414aa8092
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 22:41:50 2018 -0700
+
+    fixed name mixup in Remap::reset
+
+    it was causing inconsistent Strings Index subset results
+
+ src/hb-ot-cff-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 497e7fb264ec5cb799c038cbe693b70410b18da3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 16:47:55 2018 -0700
+
+    misc bug fixes
+
+    Added OpCode_FontMatrix to TopDictOpSet (yet to parse values)
+    fixed a wrong assert in encode_int
+
+ src/hb-cff-interp-dict-common.hh | 3 +++
+ src/hb-subset-cff-common.hh      | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit 5b453f77f804cd8421a45d8276ed3e04041da23c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 16:20:39 2018 -0700
+
+    fixed off-by-one error with offSize
+
+ src/hb-ot-cff-common.hh | 5 +++--
+ src/hb-subset-cff1.cc   | 4 ++--
+ src/hb-subset-cff2.cc   | 2 +-
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+commit 1499029a9695e26beaf72e11287be60ad9e40cfe
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 13:56:52 2018 -0700
+
+    fixed a bug
+
+ src/hb-cff-interp-dict-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0bd5912a08698fb7880e1354e45bf63ef45125a5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 13:24:27 2018 -0700
+
+    make parse_bcd locale free
+
+ src/hb-cff-interp-dict-common.hh | 92
+ +++++++++++++++++++++++++++++-----------
+ 1 file changed, 68 insertions(+), 24 deletions(-)
+
+commit bb38d0f66388ec37ee9b0e81176d60c66fc17a19
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 10:43:15 2018 -0700
+
+    Implement parse_bcd
+
+ src/hb-cff-interp-common.hh      | 15 --------------
+ src/hb-cff-interp-dict-common.hh | 44
+ ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 44 insertions(+), 15 deletions(-)
+
+commit 45e564a51917475ef6481825a6efb5b99bf1912e
+Merge: c6f75c30 d5c50927
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 11 09:46:37 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit bd75fd45cdbd0edb24568326bb7fde59d299a82c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 18:12:26 2018 +0200
+
+    [dfont] Some renaming, plus add link to reference doc
+
+ src/hb-open-file.hh | 79
+ ++++++++++++++++++++++++-----------------------------
+ 1 file changed, 35 insertions(+), 44 deletions(-)
+
+commit 4134ec1307bbaff24972e238bc5e4a403cd3f1c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 17:56:03 2018 +0200
+
+    [dfont] Sanitize only sfnt resources as OpenTypeFontFile
+
+ src/hb-open-file.hh | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+commit 6b5e4d07adb6b739dc294da513c4a7acd03977f7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 17:26:24 2018 +0200
+
+    [dfont] Minor
+
+ src/hb-open-file.hh | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+commit d5c509272f2fbd1b4c56e3b530da7e42e7f03901
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 17:18:21 2018 +0200
+
+    [dfont] Fix test expecatation and minor touch up
+
+    I have no way to authoritatively know, but looks like test font only
+    has one
+    face.  So, adjust test expectation instead.
+
+ src/hb-open-file.hh                                | 18
+ ++++++------------
+ test/shaping/data/in-house/tests/collections.tests |  2 +-
+ 2 files changed, 7 insertions(+), 13 deletions(-)
+
+commit 2b2ed1e536061cfd3a0f29522118f42b451678bd
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Jul 2 17:26:43 2018 +0430
+
+    [dfont] Add test
+
+ test/shaping/data/in-house/Makefile.sources        |   1 +
+ test/shaping/data/in-house/fonts/TestDFONT.dfont   | Bin 0 -> 3505 bytes
+ test/shaping/data/in-house/fonts/TestTTC.ttc       | Bin 0 -> 2608 bytes
+ test/shaping/data/in-house/tests/collections.tests |   6 ++++++
+ 4 files changed, 7 insertions(+)
+
+commit 9479ffefbfa3ea4ee39747e34177d26ab1ebbec9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 16:41:26 2018 +0200
+
+    [dfont] Re-enable and fix offset handling
+
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1085
+
+ src/hb-face.cc      |  5 +++--
+ src/hb-open-file.hh | 19 +++++++++++++------
+ 2 files changed, 16 insertions(+), 8 deletions(-)
+
+commit a1814e2bec3a43b9eeb4d50a67daae3fc52fd0a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:45:23 2018 +0200
+
+    Whitespace
+
+ src/hb-open-file.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 383060cc3354e12611dec3082a6fe08fdb25f652
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:41:19 2018 +0200
+
+    [ft] Invalidate advance cache if font size changed
+
+ src/hb-ft.cc | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 54998befc43ef38e47b74b3153380adbcf6279d4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:35:26 2018 +0200
+
+    [ft] Cache advances
+
+    I decided to always use the cache, instead of my previous sketch
+    direction
+    that was to only allocate and use cache if fast advances are not
+    available.
+    The cache is a mere 1kb, so just use it...
+
+    TODO: Invalidate cache on font size change.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/651
+    Fixes https://github.com/harfbuzz/harfbuzz/pull/1082
+
+ src/hb-cache.hh |  2 +-
+ src/hb-ft.cc    | 37 +++++++++++++++++--------------------
+ 2 files changed, 18 insertions(+), 21 deletions(-)
+
+commit f90bab8560816b60b4b3f2379b36c08756b21e6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:21:15 2018 +0200
+
+    [util] Add --ft-load-flags
+
+    Useful for performance testing.
+
+    Not hooked to cairo yet.  Just changes shaping, not rasterization.
+
+ util/helper-cairo.cc | 2 +-
+ util/options.cc      | 4 ++++
+ util/options.hh      | 2 ++
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+commit 93f7596254808d567b9e1e01fb4855efcd34677c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:11:10 2018 +0200
+
+    [util] Add -n shorthand for --num-iterations
+
+    Meh.
+
+ util/options.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 047a84c5dd76cdfc072de25c572e30866f87a1f7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 14:05:16 2018 +0200
+
+    [ft] Towards caching slow get_h_advance results
+
+    Related to https://github.com/harfbuzz/harfbuzz/pull/1082
+
+ src/hb-ft.cc | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+commit 237f21537842e6b471cdd6c86b98edfc0da0756c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 13:05:47 2018 +0200
+
+    [ft] Add advances() callback
+
+ src/hb-ft.cc | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+commit cbea7d49ab8d4765a2d72dcbf608d326bdf9af3d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 12:56:17 2018 +0200
+
+    [ot-font] Rename
+
+ src/hb-ot-font.cc | 74
+ +++++++++++++++++++++++++++----------------------------
+ 1 file changed, 37 insertions(+), 37 deletions(-)
+
+commit d8a67dac2a673138bb4d41cd7eab97c9ee987958
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 12:55:54 2018 +0200
+
+    [ot-font] Add advances() callbacks
+
+ src/hb-ot-font.cc | 43 ++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 42 insertions(+), 1 deletion(-)
+
+commit 0ea42e117ba2c76e118974fe114ae5d9ceef5743
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 12:22:42 2018 +0200
+
+    [cache] Minor
+
+ src/hb-cache.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0f520adaacca3c7b6d8e84a7722343184105f612
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 12:02:34 2018 +0200
+
+    Revert "Remove unused hb_cache_t"
+
+    This reverts commit 473b17af4d421f4ce7ac18c769731bb2aa4088f8.
+
+    Updates to recent changes.
+
+ src/Makefile.sources |  1 +
+ src/hb-cache.hh      | 75
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ft.cc         |  1 +
+ 3 files changed, 77 insertions(+)
+
+commit cfdea884754ed40ffa5cc00cb1ecaa86cb46a394
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 10:57:48 2018 +0200
+
+    [random] Switch to 32bit RNG
+
+ src/hb-ot-layout-gsubgpos.hh                | 7 ++++---
+ test/shaping/data/in-house/tests/rand.tests | 4 ++--
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+commit 08260c708ae6adc4efa9bde5e9ede01b7e4d42cc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 10:51:19 2018 +0200
+
+    [random] Shuffle
+
+ src/hb-ot-layout-gsub-table.hh | 5 +----
+ src/hb-ot-layout-gsubgpos.hh   | 6 ++++++
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+commit 71c9f84e7c0afe41a8987b8a4ebc2b45a22fac56
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 22:37:19 2018 +0200
+
+    Make --features rand=1 available to the user
+
+    Use rand=255 to mean "randomize".
+
+    Part of https://github.com/harfbuzz/harfbuzz/pull/803
+
+ src/hb-ot-layout-gsub-table.hh | 11 ++++-------
+ src/hb-ot-layout-gsubgpos.hh   |  1 +
+ src/hb-ot-map.cc               |  4 ++--
+ src/hb-ot-map.hh               |  3 +++
+ src/hb-ot-shape.cc             |  2 +-
+ 5 files changed, 11 insertions(+), 10 deletions(-)
+
+commit cc1c4fdf88f6953dcd07fb42ee963404657cdef4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 16:36:05 2018 +0200
+
+    Respect user's wish if they set rand feature manually
+
+    Except if the set it to 1, which would mean "randomize"... Ugly.
+
+ src/hb-ot-layout-gsub-table.hh | 30 ++++++++++++++++--------------
+ 1 file changed, 16 insertions(+), 14 deletions(-)
+
+commit 80de4bcd2677bfb0907ea7059524f918b109ac37
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 16:24:52 2018 +0200
+
+    Minor clean up of 'rand' patchset
+
+ src/hb-ot-layout-gsub-table.hh              |  7 +++++--
+ src/hb-ot-layout-gsubgpos.hh                |  7 ++++---
+ src/hb-ot-shape.cc                          | 13 ++++++-------
+ test/shaping/data/in-house/tests/rand.tests |  2 +-
+ 4 files changed, 16 insertions(+), 13 deletions(-)
+
+commit b545e27d8891f1e7f1fd034dd84abe44c839c380
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Feb 23 12:22:32 2018 -0500
+
+    Don't seed the RNG from the contents of the buffer
+
+ src/hb-ot-layout-gsubgpos.hh                | 7 ++-----
+ src/hb-ot-layout.cc                         | 5 +----
+ test/shaping/data/in-house/tests/rand.tests | 2 +-
+ 3 files changed, 4 insertions(+), 10 deletions(-)
+
+commit 2de96e846844d21888af6893378b21a33fc19232
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Sat Jan 27 19:48:38 2018 -0500
+
+    Test 'rand'
+
+ test/shaping/data/in-house/Makefile.sources              |   1 +
+ .../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf   | Bin 0 ->
+ 1352 bytes
+ test/shaping/data/in-house/tests/rand.tests              |   3 +++
+ 3 files changed, 4 insertions(+)
+
+commit f05df643b44d9bbfd742e93f02c235fc821190d0
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Jan 26 21:36:15 2018 -0500
+
+    Allow requesting a specific glyph for 'rand'
+
+    Randomization only happens by default. If the user specifies a
+    value for
+    'rand', that value is respected.
+
+ src/hb-ot-map.cc   | 3 ++-
+ src/hb-ot-map.hh   | 4 +++-
+ src/hb-ot-shape.cc | 7 ++++++-
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+commit c2a75e07e54314f6c611dda0f050ed5f09909e43
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Thu Jan 25 14:22:03 2018 -0500
+
+    Implement 'rand'
+
+ src/hb-ot-layout-gsub-table.hh | 19 ++++++++++++-------
+ src/hb-ot-layout-gsubgpos.hh   |  8 ++++++++
+ src/hb-ot-layout.cc            |  8 ++++++++
+ src/hb-ot-map.cc               |  7 +++++--
+ src/hb-ot-map.hh               |  4 +++-
+ src/hb-ot-shape.cc             |  1 +
+ 6 files changed, 37 insertions(+), 10 deletions(-)
+
+commit c6f75c3049685440d166bd4169b36abac2df4fdd
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 10 17:02:31 2018 -0700
+
+    fix build attempt
+
+ src/hb-ot-cff1-table.hh | 70
+ ++++++++++++++++++++++++-------------------------
+ src/hb-subset-cff1.cc   | 16 +++++------
+ 2 files changed, 43 insertions(+), 43 deletions(-)
+
+commit 96471fe8593575deceb44d3757c227f65f10a25e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 01:39:23 2018 +0200
+
+    [uniscribe] Fix build
+
+ src/hb-uniscribe.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit cc52e53cf0cb76809145ae7407a8b613e9e61153
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 10 16:27:49 2018 -0700
+
+    Removed unused subr subset code
+
+ src/hb-subset-cff-common.hh | 98
+ ++-------------------------------------------
+ src/hb-subset-cff1.cc       | 92
+ +++++-------------------------------------
+ src/hb-subset-cff2.cc       | 90
+ ++++-------------------------------------
+ 3 files changed, 22 insertions(+), 258 deletions(-)
+
+commit becd84aa2f2902ea9d2d1677b28945e103a68816
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 01:26:18 2018 +0200
+
+    Add HB_FEATURE_GLOBAL_START/END
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1141
+
+    New API:
+    HB_FEATURE_GLOBAL_START
+    HB_FEATURE_GLOBAL_END
+
+ docs/harfbuzz-sections.txt |  2 ++
+ src/hb-common.cc           |  4 ++--
+ src/hb-common.h            | 13 +++++++++++++
+ 3 files changed, 17 insertions(+), 2 deletions(-)
+
+commit 13a8786c7c580651d8a6db9345b9aa85ca8ed956
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 01:07:06 2018 +0200
+
+    Add (unused) hb_array_t<>
+
+ src/hb-dsalgs.hh | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+commit bccf3e1827eec07433340eea705597201b6d0a32
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Sep 11 01:04:50 2018 +0200
+
+    Minor
+
+ src/hb-open-type.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit dff2c45f1e2a30767f6813d3cb6a70978d98d424
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 23:29:26 2018 +0200
+
+    Port rest from VAR to UnsizedArrayOf<>
+
+ src/hb-aat-layout-common.hh     | 14 +++++++-------
+ src/hb-aat-layout-morx-table.hh | 16 ++++++++--------
+ src/hb-open-type.hh             | 10 +++++-----
+ src/hb-ot-cmap-table.hh         |  8 +++++---
+ src/hb-ot-color-cbdt-table.hh   | 16 ++++++++--------
+ src/hb-ot-glyf-table.hh         | 10 +++++-----
+ src/hb-ot-hdmx-table.hh         | 30 +++++++++++++-----------------
+ src/hb-ot-hmtx-table.hh         |  8 ++++----
+ src/hb-ot-kern-table.hh         | 20 ++++++++++----------
+ src/hb-ot-layout-common.hh      |  9 +++++----
+ src/hb-ot-layout-gpos-table.hh  | 26 +++++++++++++-------------
+ src/hb-ot-math-table.hh         | 36 +++++++++++++++++++-----------------
+ src/hb-ot-maxp-table.hh         |  2 +-
+ src/hb-ot-name-table.hh         | 13 +++++++------
+ src/hb-ot-post-table.hh         |  5 +++--
+ 15 files changed, 113 insertions(+), 110 deletions(-)
+
+commit 1666b89e300c86347dc82131423463cbfed8cc0f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Sep 10 16:00:20 2018 -0700
+
+    subset CFF1 String Index
+
+    Repurposed FDMap as Remap then subclassed for remapping SIDs
+    misc code cleanup
+
+ src/hb-cff-interp-common.hh      |   2 -
+ src/hb-cff-interp-dict-common.hh |  12 +-
+ src/hb-ot-cff-common.hh          |  96 +++++++++--
+ src/hb-ot-cff1-table.hh          | 251 +++++++++++++++++++----------
+ src/hb-ot-cff2-table.hh          |  12 +-
+ src/hb-subset-cff-common.cc      |  24 +--
+ src/hb-subset-cff-common.hh      |  20 ++-
+ src/hb-subset-cff1.cc            | 334
+ ++++++++++++++++++++++++++++++++-------
+ src/hb-subset-cff2.cc            |   8 +-
+ 9 files changed, 565 insertions(+), 194 deletions(-)
+
+commit 9507b05a7a65962d5d02eb424e4f5d8570976f4e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 23:18:07 2018 +0200
+
+    Simplify sanitize->check_array()
+
+    Fix a bug in CBDT sanitize, and redundant check in avar.
+
+ src/hb-aat-layout-common.hh     | 10 ++++------
+ src/hb-aat-layout-morx-table.hh |  2 +-
+ src/hb-machinery.hh             |  3 ++-
+ src/hb-open-type.hh             |  6 +++---
+ src/hb-ot-color-cbdt-table.hh   |  4 ++--
+ src/hb-ot-kern-table.hh         |  2 +-
+ src/hb-ot-layout-common.hh      |  2 +-
+ src/hb-ot-layout-gpos-table.hh  |  8 ++++----
+ src/hb-ot-layout-gsubgpos.hh    |  4 ++--
+ src/hb-ot-math-table.hh         |  8 ++------
+ src/hb-ot-name-table.hh         |  2 +-
+ src/hb-ot-var-avar-table.hh     |  4 ++--
+ src/hb-ot-var-fvar-table.hh     |  2 +-
+ src/hb-ot-var-hvar-table.hh     |  2 +-
+ src/hb-ot-var-mvar-table.hh     |  2 +-
+ 15 files changed, 28 insertions(+), 33 deletions(-)
+
+commit bc485a98122131efc4768fef9147823f2bce146b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 23:02:24 2018 +0200
+
+    Port some VAR arrays to UnsizedArrayOf<>
+
+    Fix avar sanitize().
+
+ src/hb-ot-layout-gsubgpos.hh | 59
+ +++++++++++++++++++++++---------------------
+ src/hb-ot-var-avar-table.hh  | 10 +++++---
+ src/hb-ot-var-fvar-table.hh  |  7 +++---
+ src/hb-ot-var-hvar-table.hh  |  9 ++++---
+ src/hb-ot-var-mvar-table.hh  |  9 ++++---
+ 5 files changed, 51 insertions(+), 43 deletions(-)
+
+commit 1bc7a8d6c4deb9fa6e010d7be08b68cad88579ae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 22:51:26 2018 +0200
+
+    [indic] Cache hb_options().uniscribe_bug_compatible on indic_plan
+
+ src/hb-ot-shape-complex-indic.cc | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+commit 24f1d9622489a016904314a5d4e3c637da2e1c77
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 18:19:37 2018 +0200
+
+    Unbreak HB_OPTIONS
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1154
+
+ src/hb-debug.hh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit e46c51f1e985ac9c0ffa90fda4ea436d54b4009c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 17:38:19 2018 +0200
+
+    [indic] Do NOT allow matra after Halant,ZWJ
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/556
+
+    Devanagari regresses 12 tests, and Gujarati 2.  See:
+
+      https://github.com/harfbuzz/harfbuzz/issues/556#issuecomment-419957472
+
+    New numbers:
+
+    BENGALI: 353725 out of 354188 tests passed. 463 failed (0.130722%)
+    DEVANAGARI: 707299 out of 707394 tests passed. 95 failed (0.0134296%)
+    GUJARATI: 366353 out of 366457 tests passed. 104 failed (0.0283799%)
+    GURMUKHI: 60729 out of 60747 tests passed. 18 failed (0.0296311%)
+    KANNADA: 951300 out of 951913 tests passed. 613 failed (0.0643966%)
+    MALAYALAM: 1048136 out of 1048334 tests passed. 198 failed
+    (0.0188871%)
+    ORIYA: 42327 out of 42329 tests passed. 2 failed (0.00472489%)
+    SINHALA: 271596 out of 271847 tests passed. 251 failed (0.0923313%)
+    TAMIL: 1091754 out of 1091754 tests passed. 0 failed (0%)
+    TELUGU: 970555 out of 970573 tests passed. 18 failed (0.00185457%)
+
+ src/hb-ot-shape-complex-indic-machine.hh | 1688
+ ++++++++++++++----------------
+ src/hb-ot-shape-complex-indic-machine.rl |    2 +-
+ 2 files changed, 784 insertions(+), 906 deletions(-)
+
+commit 5dfd6e07626a9022a995eb7fa16767eff66c6047
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 15:45:32 2018 +0200
+
+    Fix sanitize or Context Rule
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1110
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 20a11a824d2a07a8544649477ad03e809bdd8e19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 13:56:28 2018 +0200
+
+    Revert "[subset] Disable GSUB/GPOS subsetting for now"
+
+    This reverts commit 616fd34a69bb69bc35c7e4ea939e71c3ea2e92cb.
+
+ src/hb-subset.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 54d332dd9b0263821376161cdffb60ffb3c7847f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 11:37:24 2018 +0200
+
+    1.9.0
+
+ NEWS             | 19 +++++++++++++++++++
+ configure.ac     |  2 +-
+ src/hb-face.cc   | 10 +++++-----
+ src/hb-unicode.h |  5 +++++
+ src/hb-version.h |  6 +++---
+ 5 files changed, 33 insertions(+), 9 deletions(-)
+
+commit 616fd34a69bb69bc35c7e4ea939e71c3ea2e92cb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 11:19:49 2018 +0200
+
+    [subset] Disable GSUB/GPOS subsetting for now
+
+    So I can get a release out.  I haven't debugged those yet, and they
+    are producing bad tables.
+
+ src/hb-subset.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit d42f0e5809964136911cbbd845bc423a8dfd5e31
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 10 11:05:33 2018 +0200
+
+    [atomic] Fix pointer type passed to InterlockedExchangeAdd()
+
+    John Emmas reported on mailing list that build with MSVC is failing.
+    Not sure why bots don't catch it, but this should fix.
+
+ src/hb-atomic.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit fda994e1d45c4d34601af7272f37ea257f92a3d8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 7 15:02:57 2018 -0400
+
+    Use enum instead of "static const" in class scope
+
+    Technically, static const needs an out-of-class definition.  Eg:
+
+      CXXLD    libharfbuzz-subset.la
+    Undefined symbols for architecture x86_64:
+      "OT::FeatureVariationRecord::min_size", referenced from:
+          bool OT::GSUBGPOS::subset<OT::PosLookup>(hb_subset_context_t*)
+          constin libharfbuzz_subset_la-hb-subset.o
+          bool OT::GSUBGPOS::subset<OT::SubstLookup>(hb_subset_context_t*)
+          constin libharfbuzz_subset_la-hb-subset.o
+      "OT::Record<OT::LangSys>::min_size", referenced from:
+          OT::Script::subset(hb_subset_context_t*) constin
+          libharfbuzz_subset_la-hb-subset.o
+      "OT::IntType<unsigned short, 2u>::min_size", referenced from:
+          OT::Script::subset(hb_subset_context_t*) constin
+          libharfbuzz_subset_la-hb-subset.o
+          OT::RecordListOf<OT::Feature>::subset(hb_subset_context_t*)
+          const  in libharfbuzz_subset_la-hb-subset.o
+    ld: symbol(s) not found for architecture x86_64
+    collect2: ld returned 1 exit status
+    make[4]: *** [libharfbuzz-subset.la] Error 1
+    make[3]: *** [all-recursive] Error 1
+    make[2]: *** [all] Error 2
+    make[1]: *** [all-recursive] Error 1
+    make: *** [all] Error 2
+    Exited with code 2
+
+ src/hb-buffer.hh           |  2 +-
+ src/hb-machinery.hh        |  8 ++++----
+ src/hb-open-file.hh        |  2 +-
+ src/hb-open-type.hh        |  2 +-
+ src/hb-ot-layout-common.hh |  2 +-
+ src/hb-ot-layout.cc        |  4 ++--
+ src/hb-set-digest.hh       |  4 ++--
+ src/hb-set.hh              | 12 ++++++------
+ 8 files changed, 18 insertions(+), 18 deletions(-)
+
+commit 1e88b1755c37eaa171c08f7bedb93f110238c80f
+Merge: 22b88632 ebe67137
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Sep 7 10:50:55 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit ebe67137ab3559c2c6aaf53442ca223cb34df5af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 7 10:46:13 2018 -0400
+
+    Try fixing bots
+
+ src/hb-ot-layout-common.hh | 32 ++++++++++++++++++--------------
+ 1 file changed, 18 insertions(+), 14 deletions(-)
+
+commit 5f17dbc3025093308d2191a4abd2eec24db35c0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Sep 7 10:24:22 2018 -0400
+
+    [subset] Fix div-by-zero
+
+ src/hb-subset.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 22b88632d5bd3676642b0a1d93f27e47438c140b
+Merge: 2a74536a 21bf1470
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 6 22:27:44 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 2a74536aae443a8b7f23ed018dec14a013c04dfe
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 6 18:26:13 2018 -0700
+
+    fix build attempt ^2
+
+    Added hb-ot-cff1-table.cc to hb-subset sources
+    Deleted unused variable (charset)
+
+ src/Makefile.sources  | 1 +
+ src/hb-subset-cff1.cc | 1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+commit 55268df9d4b287883c8266e316cda44f4011f424
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 6 17:56:05 2018 -0700
+
+    fix build attempt
+
+    Added HB_INTERNAL to static funtion declarations
+
+ src/hb-ot-cff1-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit aca73c9df2054f62cf10a5c27bc5fa7823747f8b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Sep 6 17:28:15 2018 -0700
+
+    subset CFF1 Encoding & Charset
+
+    fixed misc Charset bugs
+    added source file hb-ot-cff1.table.cc
+    renamed things for clarity & consistency
+
+ src/Makefile.sources             |   1 +
+ src/hb-cff-interp-dict-common.hh |  15 +-
+ src/hb-ot-cff-common.hh          |  34 ++--
+ src/hb-ot-cff1-table.cc          | 130 +++++++++++++
+ src/hb-ot-cff1-table.hh          | 403
+ ++++++++++++++++++++++++++++++++-------
+ src/hb-ot-cff2-table.hh          |  24 +--
+ src/hb-subset-cff1.cc            | 247 ++++++++++++++++++++----
+ src/hb-subset-cff2.cc            |  30 +--
+ 8 files changed, 737 insertions(+), 147 deletions(-)
+
+commit 21bf147054f6b5bd1c430c0e02a8c4058ed229a1
+Author: Garret Rieger <grieger@google.com>
+Date:   Wed Sep 5 18:04:52 2018 -0700
+
+    [subset] Fix hdmx subsetted size calculation.
+
+ src/hb-ot-hdmx-table.hh                         |  14 ++++++++++----
+ test/api/fonts/Roboto-Regular.multihdmx.a.ttf   | Bin 0 -> 2052 bytes
+ test/api/fonts/Roboto-Regular.multihdmx.abc.ttf | Bin 0 -> 2468 bytes
+ test/api/test-subset-hdmx.c                     |  20
+ ++++++++++++++++++++
+ 4 files changed, 30 insertions(+), 4 deletions(-)
+
+commit 1e6599f59680c81356b2e9ddddb61252490337a0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 5 19:29:42 2018 -0700
+
+    Fix older compilers re '>>' at nested template declarations
+
+ src/hb-ot-layout-gsub-table.hh | 8 ++++----
+ src/hb-subset.cc               | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit a1e5e07c735091e82d66ac56a4e27341f589369d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Sep 5 16:24:28 2018 -0700
+
+    [subset] Hook up GSUB/GPOS, but still disabled
+
+    They are still in the drop list.
+
+ src/hb-ot-hdmx-table.hh |  3 +-
+ src/hb-subset.cc        | 75
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 77 insertions(+), 1 deletion(-)
+
+commit 0d160d5ff5158fd4190201becd652c8f28ef4430
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 20:50:11 2018 -0700
+
+    [subset] Implement subsetting of SingleSubst
+
+ src/hb-machinery.hh            |  2 ++
+ src/hb-null.hh                 | 43 +++++++++++++++++++-----------
+ src/hb-ot-layout-gsub-table.hh | 59
+ +++++++++++++++++++++++++++++++++++-------
+ src/hb-vector.hh               |  2 ++
+ 4 files changed, 81 insertions(+), 25 deletions(-)
+
+commit 5ea03d2951375bfcc1258c2c0b5c33efc6ebf7f8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 4 11:29:15 2018 -0700
+
+    fix build by untemplatizing DictOpSet & DictVal
+
+    as they aren't instantiated with BlendArg (yet)
+
+ src/hb-cff-interp-dict-common.hh | 21 +++++++++------------
+ src/hb-cff2-interp-cs.hh         |  1 -
+ src/hb-ot-cff1-table.hh          |  8 ++++----
+ src/hb-ot-cff2-table.hh          | 16 ++++++++--------
+ src/hb-subset-cff-common.hh      |  4 ++--
+ 5 files changed, 23 insertions(+), 27 deletions(-)
+
+commit f2d299b0b75fd110cdc6b16de31e7212e292cc14
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Tue Sep 4 10:25:21 2018 -0700
+
+    Drop hints from CFF2 charstrings
+
+    Templatized ArgStack so it may store the default value along with
+    blend deltas as BlendArg while parsing blend operator arguments in
+    CFF2 charstring
+    Added get_region_count() method to VarRegionList & VariationStore
+
+ src/hb-cff-interp-common.hh | 67 +++++++++++++++++++++++++++------
+ src/hb-cff1-interp-cs.hh    |  5 ++-
+ src/hb-cff2-interp-cs.hh    | 91
+ +++++++++++++++++++++++++++++++++++++++------
+ src/hb-ot-cff2-table.hh     | 22 ++++++-----
+ src/hb-ot-layout-common.hh  |  6 +++
+ src/hb-subset-cff-common.hh | 60 ++++++++++++++++--------------
+ src/hb-subset-cff1.cc       |  5 ++-
+ src/hb-subset-cff2.cc       | 54 ++++++++++++++++++++++-----
+ 8 files changed, 235 insertions(+), 75 deletions(-)
+
+commit 3f00d0b0df14d69859b15568ff28a810d08f59ea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 18:54:32 2018 -0700
+
+    [subset] Keep glyph set in plan
+
+    Should remove the vector version at some point...
+
+ src/hb-subset-plan.cc | 19 ++++++++++---------
+ src/hb-subset-plan.hh |  3 +--
+ 2 files changed, 11 insertions(+), 11 deletions(-)
+
+commit dc50493a8da05d6561242136d63cae836486c150
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 18:23:23 2018 -0700
+
+    [subset] Towards subsetting SingleSubstFormat1
+
+    Why does subset plan not have a hb_set_t of glyphs?
+
+ src/hb-machinery.hh            | 10 +++++++++-
+ src/hb-ot-layout-gsub-table.hh | 12 +++++++++++-
+ 2 files changed, 20 insertions(+), 2 deletions(-)
+
+commit 339d3603b916cebf24ff86d9842b766261e1b262
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 17:33:34 2018 -0700
+
+    [subset] Wire up subset() call down to subtables
+
+ src/hb-ot-layout-common.hh     | 36 +++++++++++++++++++++++
+ src/hb-ot-layout-gpos-table.hh | 67
+ +++++++++++++++++++++++++++++++++++++++---
+ src/hb-ot-layout-gsub-table.hh | 54 ++++++++++++++++++++++++++++------
+ src/hb-ot-layout-gsubgpos.hh   | 42 ++++++++++++++++++++++++++
+ 4 files changed, 186 insertions(+), 13 deletions(-)
+
+commit 7b2ef551da0d53cd94106035b1f065a759cf3cd5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 17:16:09 2018 -0700
+
+    Templatize Lookup::sanitize()
+
+ src/hb-ot-layout-common.hh     | 40
+ ++++++++++++++++++++++++++++------------
+ src/hb-ot-layout-gpos-table.hh |  7 ++-----
+ src/hb-ot-layout-gsub-table.hh | 25 +++----------------------
+ 3 files changed, 33 insertions(+), 39 deletions(-)
+
+commit 9c3747c5e50423e0a7202f249728d5c5b2b09073
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 16:53:03 2018 -0700
+
+    [subset] More
+
+ src/hb-ot-layout-gpos-table.hh | 10 +++++----
+ src/hb-ot-layout-gsub-table.hh | 48
+ +++++++++++++++++++++---------------------
+ src/hb-ot-layout-gsubgpos.hh   | 22 +++++++++++++------
+ 3 files changed, 45 insertions(+), 35 deletions(-)
+
+commit 6d618522d63a94230ad708fc49c1c73927da0137
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 16:41:28 2018 -0700
+
+    Templatize GSUBGPOS::sanitize()
+
+ src/hb-ot-layout-gpos-table.hh |  6 +-----
+ src/hb-ot-layout-gsub-table.hh | 14 +++++---------
+ src/hb-ot-layout-gsubgpos.hh   |  4 +++-
+ 3 files changed, 9 insertions(+), 15 deletions(-)
+
+commit 49c44b58f6c2536ea5f403c54a40cab41b905150
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Sep 3 16:37:17 2018 -0700
+
+    [subset] Fix serialize_subset() calls
+
+    Ouch.
+
+ src/hb-open-type.hh            |  2 +-
+ src/hb-ot-layout-common.hh     |  6 +++---
+ src/hb-ot-layout-gsub-table.hh | 13 ++++++-------
+ src/hb-ot-layout-gsubgpos.hh   |  6 +++---
+ 4 files changed, 13 insertions(+), 14 deletions(-)
+
+commit 7c9cfa2b4002c18585a26134ab987ceb7ebc97a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 2 19:47:50 2018 -0700
+
+    Add intersects() method to GSUB/GPOS lookups
+
+ src/hb-ot-layout-common.hh     |  77 +++++++++--
+ src/hb-ot-layout-gpos-table.hh | 103 ++++++++++----
+ src/hb-ot-layout-gsub-table.hh | 205 +++++++++++++++++++--------
+ src/hb-ot-layout-gsubgpos.hh   | 306
+ ++++++++++++++++++++++++++++++++---------
+ 4 files changed, 528 insertions(+), 163 deletions(-)
+
+commit 61ce62e55455bb0d6c9db3b076676ab18e51d449
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Sep 2 17:00:27 2018 -0700
+
+    [subset] Minor
+
+    Remove Lookup::subset().
+
+ src/hb-ot-layout-common.hh   | 11 -----------
+ src/hb-ot-layout-gsubgpos.hh |  2 +-
+ 2 files changed, 1 insertion(+), 12 deletions(-)
+
+commit bfa72a9a72a15d977f503f12eef376a355679d76
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Sep 1 18:34:50 2018 -0700
+
+    [subset] Towards GSUB/GPOS subsetting
+
+    Add subset() call for GSUBGPOS struct and its dependencies.
+    Not hooked up anywhere.
+
+ src/hb-machinery.hh            | 10 ++++--
+ src/hb-open-type.hh            | 25 ++++++++++++-
+ src/hb-ot-layout-common.hh     | 80
+ +++++++++++++++++++++++++++++++++++-------
+ src/hb-ot-layout-gdef-table.hh | 33 ++++++++++-------
+ src/hb-ot-layout-gsub-table.hh | 11 ++++--
+ src/hb-ot-layout-gsubgpos.hh   | 19 ++++++++++
+ 6 files changed, 145 insertions(+), 33 deletions(-)
+
+commit 6803ed8674028a656957910381150ab28d75a5f8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 17:11:08 2018 -0700
+
+    [serialize] Add reset()
+
+ src/hb-machinery.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit e58b190292f85c9676fe14cf63d2831d4d6e6bab
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 16:46:35 2018 -0700
+
+    [subset] De-templatize hb_subset_context_t
+
+    We're going to (finally) use virtual methods for
+    hb_serialize_context_t
+    customization, so don't need to carry a Serializer template variable
+    around...  Simplifies code.
+
+ src/hb-machinery.hh            | 2 +-
+ src/hb-ot-layout-gsub-table.hh | 5 ++---
+ src/hb-subset.hh               | 7 +++----
+ 3 files changed, 6 insertions(+), 8 deletions(-)
+
+commit 22acd424ca77c16d28405021f06c5562497920ab
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 16:38:04 2018 -0700
+
+    [serialize] Add a couple small methods
+
+ src/hb-machinery.hh            | 25 +++++++++++++++++--------
+ src/hb-open-file.hh            |  3 +--
+ src/hb-ot-layout-gsub-table.hh |  1 +
+ 3 files changed, 19 insertions(+), 10 deletions(-)
+
+commit d1f29908c281b1685eea00b71bae934d9f1f20eb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 16:31:00 2018 -0700
+
+    [subset] Add hb_subset_context_t<>
+
+ src/hb-open-type.hh            |  1 +
+ src/hb-ot-cmap-table.hh        |  1 -
+ src/hb-ot-hdmx-table.hh        |  1 -
+ src/hb-ot-hmtx-table.hh        |  1 -
+ src/hb-ot-layout-gsub-table.hh |  9 +++++++++
+ src/hb-ot-maxp-table.hh        |  1 -
+ src/hb-ot-os2-table.hh         |  1 -
+ src/hb-ot-post-table.hh        |  1 -
+ src/hb-subset.hh               | 21 +++++++++++++++++++++
+ 9 files changed, 31 insertions(+), 6 deletions(-)
+
+commit fcf177885b4c3d732ffeb82936da906969a269d3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 31 16:28:47 2018 -0700
+
+    templatized ArgStack as a prep to store blends
+
+ src/hb-cff-interp-common.hh      | 46
+ +++++++++++++++++++++---------------
+ src/hb-cff-interp-cs-common.hh   | 41 ++++++++++++++++++--------------
+ src/hb-cff-interp-dict-common.hh | 35 ++++++++++++++++-----------
+ src/hb-cff1-interp-cs.hh         | 15 +++++++-----
+ src/hb-cff2-interp-cs.hh         | 14 +++++++----
+ src/hb-ot-cff1-table.hh          | 32 ++++++++++++-------------
+ src/hb-ot-cff2-table.hh          | 51
+ ++++++++++++++++++++++++++--------------
+ src/hb-subset-cff-common.hh      |  4 ++--
+ src/hb-subset-cff1.cc            |  1 -
+ src/hb-subset-cff2.cc            |  2 +-
+ 10 files changed, 142 insertions(+), 99 deletions(-)
+
+commit 968168bf0e369927cd6a7f63608d844abe123a7b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 31 13:28:16 2018 -0700
+
+    drop hints from CFF1 charstrings
+
+    renamed confusing Stack.size to Stack.count
+
+ src/hb-cff-interp-common.hh      |  43 +++++++-----
+ src/hb-cff-interp-cs-common.hh   | 140
+ +++++++++++++++++----------------------
+ src/hb-cff-interp-dict-common.hh |   4 +-
+ src/hb-cff1-interp-cs.hh         |  14 ++--
+ src/hb-cff2-interp-cs.hh         |  18 ++---
+ src/hb-ot-cff1-table.hh          |  26 ++++----
+ src/hb-ot-cff2-table.hh          |  20 +++---
+ src/hb-subset-cff1.cc            |  53 ++++++++-------
+ src/hb-subset-cff2.cc            |  69 +++++++++----------
+ 9 files changed, 190 insertions(+), 197 deletions(-)
+
+commit aba0a945c5f8724cc7bd1a9b7f7b5df1c64b03f4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 13:25:19 2018 -0700
+
+    [subset] Add hb-subset-input.hh and make hb-subset.hh toplevel include
+
+ src/Makefile.sources    |  1 +
+ src/hb-ot-cmap-table.hh |  2 +-
+ src/hb-ot-glyf-table.hh |  2 --
+ src/hb-ot-hdmx-table.hh |  2 +-
+ src/hb-ot-hmtx-table.hh |  2 +-
+ src/hb-ot-maxp-table.hh |  2 +-
+ src/hb-ot-os2-table.hh  |  2 +-
+ src/hb-ot-post-table.hh |  2 +-
+ src/hb-subset-glyf.cc   |  1 -
+ src/hb-subset-glyf.hh   |  2 +-
+ src/hb-subset-input.hh  | 57
+ +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-subset-plan.cc   |  3 +--
+ src/hb-subset-plan.hh   |  2 +-
+ src/hb-subset.cc        |  3 +--
+ src/hb-subset.hh        | 23 +++-----------------
+ 15 files changed, 71 insertions(+), 35 deletions(-)
+
+commit 18d01eac7f2870e2804ceed2c70a604a5dc6a320
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 31 13:00:57 2018 -0700
+
+    Minor
+
+ src/hb-ot-shape-complex-arabic-fallback.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 8c5e03b5415f83312719ebb3cd284229e52a4843
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 30 17:21:56 2018 -0700
+
+    Added drop_hints to SubrFlattener
+
+ src/hb-cff-interp-cs-common.hh | 20 +++++++++++++++++++-
+ src/hb-subset-cff-common.hh    | 18 ++++++++++++++----
+ src/hb-subset-cff1.cc          | 35 ++++++++++++++++++++++------------
+ src/hb-subset-cff2.cc          | 43
+ ++++++++++++++++++++++++++----------------
+ 4 files changed, 83 insertions(+), 33 deletions(-)
+
+commit a23b892fe6cc4859a30edc7ffc003ab7624aa5f0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 29 18:28:39 2018 -0700
+
+    Shuffle
+
+ src/hb-machinery.hh | 62
+ +++++++++++++++++++++++++++--------------------------
+ 1 file changed, 32 insertions(+), 30 deletions(-)
+
+commit 93fe0faaee45b8fb646f7aa33620105c62193885
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 29 18:24:03 2018 -0700
+
+    [subset] Clean up hb_subset_input_t API
+
+ src/hb-subset-input.cc           | 44
+ +++++++++++++++++++---------------------
+ src/hb-subset-plan.cc            |  4 ++--
+ src/hb-subset-plan.hh            | 10 ++++-----
+ src/hb-subset.cc                 |  2 +-
+ src/hb-subset.h                  | 14 +++++++++----
+ src/hb-subset.hh                 |  4 ++--
+ test/api/test-subset-glyf.c      | 10 ++++-----
+ test/fuzzing/hb-subset-fuzzer.cc | 10 ++++-----
+ util/hb-subset.cc                |  3 +--
+ 9 files changed, 52 insertions(+), 49 deletions(-)
+
+commit 9fd08cc238f8e2f7be1eaefca110021382efe606
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 18:18:18 2018 -0700
+
+    CFF2 subroutine flattner
+
+    Factored out CFF1 & CFF2 common subsetting code in
+    hb-subset-cff-common.hh
+
+ src/hb-cff2-interp-cs.hh    |  34 +++++--
+ src/hb-subset-cff-common.hh | 154 +++++++++++++++++++++++++++++
+ src/hb-subset-cff1.cc       | 135 +++-----------------------
+ src/hb-subset-cff2.cc       | 229
+ ++++++++++++++++++--------------------------
+ 4 files changed, 285 insertions(+), 267 deletions(-)
+
+commit d237ce71810045ee400c52740cd8ab6e1113aada
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 29 18:13:07 2018 -0700
+
+    [subset] Bail if subsetting a table failed
+
+ src/hb-subset.cc | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit f39166f0c0c09fac7874fda6b0b0825f20768e3e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 29 18:09:55 2018 -0700
+
+    [subset] Remove unused hb_subset_profile_t
+
+    We might reintroduce it later, but for now remove, as it was unused.
+    Some things that should have been in this object (drop_hints, etc)
+    are already in hb_subset_input_t.  So, for now, keep everything there.
+
+ src/hb-subset-plan.cc            |  3 +--
+ src/hb-subset-plan.hh            |  1 -
+ src/hb-subset.cc                 | 39
+ +++------------------------------------
+ src/hb-subset.h                  | 16 +---------------
+ test/api/hb-subset-test.h        |  4 +---
+ test/api/test-subset-hdmx.c      |  8 ++------
+ test/api/test-subset-hmtx.c      |  4 +---
+ test/api/test-subset.c           | 12 +++---------
+ test/fuzzing/hb-subset-fuzzer.cc |  5 +----
+ util/hb-subset.cc                |  4 +---
+ 10 files changed, 14 insertions(+), 82 deletions(-)
+
+commit 2ccc322cf88a01248aa5df88a5073db3dfb40eea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 29 16:38:04 2018 -0700
+
+    [ot-font] Clean up cmap with gid=0
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1145
+
+ src/hb-ot-cmap-table.hh | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+commit 0c7b633f528bae4a0cf5ca816f75a0d84206b3fb
+Author: Ross Burton <ross@burtonini.com>
+Date:   Wed Aug 29 22:37:39 2018 +0100
+
+    Delete pkg.m4
+
+    pkg.m4 is provided by pkg-config, which is a requirement to build,
+    and this copy is ancient.  Delete it to avoid it being used instead
+    of the host copy.
+
+ m4/pkg.m4 | 157
+ --------------------------------------------------------------
+ 1 file changed, 157 deletions(-)
+
+commit b95bf075d7b62baf7d6fa1d8f0d1f16fad934975
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 14:41:52 2018 -0700
+
+    fix build attempt ^2
+
+ src/hb-subset-cff1.cc | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 1d1afddfd21155ef136c2d96b1d6c286bdc8925f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 13:36:39 2018 -0700
+
+    corrected preprocessor guards
+
+ src/hb-cff-interp-common.hh      | 6 +++---
+ src/hb-cff-interp-cs-common.hh   | 6 +++---
+ src/hb-cff-interp-dict-common.hh | 6 +++---
+ src/hb-ot-cff-common.hh          | 6 +++---
+ src/hb-subset-cff-common.hh      | 6 +++---
+ 5 files changed, 15 insertions(+), 15 deletions(-)
+
+commit 8af9690ac7ce41fb1db878d556df5c4ee624eaa0
+Merge: 0ad081ec fee0f41c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 13:26:17 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+    Renamed cff "private" source/headers without the suffix
+
+commit 0ad081ec324e734cfca60d4d2c36a1be5bc8a067
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 12:56:48 2018 -0700
+
+    attempt to fix build failure
+
+ src/hb-subset-cff1.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit a11420b48c405e1a43e2ba62893e9a0872e5f496
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 29 12:14:30 2018 -0700
+
+    Subroutine flattener for CFF1
+
+    Subr-flattened charstrings are temporarily re-encoded in ByteStrBuff
+    during "plan" phase, then copied to hb_serialize_context_t during
+    "write" phase
+
+    CSOpSet may callback opcode processing "virtual" functions via CRTP
+
+    Numer struct may store a value as fixed optionally in addition to
+    int and float
+
+ src/hb-cff-interp-common-private.hh    |  53 ++++++++++--
+ src/hb-cff-interp-cs-common-private.hh | 109 ++++++++++++++++++-----
+ src/hb-cff1-interp-cs.hh               |  35 +++++---
+ src/hb-cff2-interp-cs.hh               |  14 +--
+ src/hb-ot-cff-common-private.hh        |  10 +--
+ src/hb-subset-cff-common-private.hh    | 102 +++++++++++++++++++++-
+ src/hb-subset-cff1.cc                  | 152
+ ++++++++++++++++++++++-----------
+ src/hb-subset-cff2.cc                  |   7 +-
+ 8 files changed, 372 insertions(+), 110 deletions(-)
+
+commit fee0f41c6c1e50621d10b07802ca36a9b295b53d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 28 18:27:41 2018 -0700
+
+    Don't declare extern symbols as inline
+
+    clang -O3 was completely removing _get_gdef(), causing link
+    failure when needed from another compilation unit.  Surprisingly,
+    "extern inline" didn't fix it.
+
+ src/hb-ot-layout.cc | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 967741e4c468ebf0a40f91934ed1923506099806
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 28 18:18:02 2018 -0700
+
+    Add explicit to hb_auto_t 1param constructors
+
+ src/hb-dsalgs.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit c0a3f38f78362a183b30afd109dcebfca563d144
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 28 17:22:38 2018 -0700
+
+    Fix distcheck
+
+ src/Makefile.sources | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 2dde6c803a9e50c5bff74095187b0cb2e12eebdd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 28 11:02:00 2018 -0700
+
+    Explicitly pass reference in hb_auto_t constructor
+
+    Fixes clang bots as well as fuzzer issue.
+
+ src/hb-dsalgs.hh | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+commit a26806801005c28115ae9e48bdcf3bbbc1bcd767
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 15:18:46 2018 -0700
+
+    [ot-face] Remove tables_t. The face_data_t is what tables_t was
+
+ src/hb-aat-layout.cc |  4 ++--
+ src/hb-face.cc       |  6 +++---
+ src/hb-ot-face.cc    |  8 ++++----
+ src/hb-ot-face.hh    | 28 ++++++++++++----------------
+ src/hb-ot-font.cc    | 25 +++++++++++--------------
+ src/hb-ot-layout.cc  | 36 ++++++++++++++++++------------------
+ src/hb-ot-math.cc    |  4 ++--
+ src/hb-ot-var.cc     |  4 ++--
+ 8 files changed, 54 insertions(+), 61 deletions(-)
+
+commit 3a0b3a29cc246d0b1e5989c9e8c1e6d544046dcc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 15:11:24 2018 -0700
+
+    Free up hb-ot-face.hh from includes
+
+    There might be a better way to do this, but I couldn't find...
+
+ src/hb-face.cc                 |  1 +
+ src/hb-ot-cmap-table.hh        |  1 +
+ src/hb-ot-color-cbdt-table.hh  |  2 ++
+ src/hb-ot-face.cc              | 10 ++++++++++
+ src/hb-ot-face.hh              | 15 ++-------------
+ src/hb-ot-font.cc              |  7 +++++++
+ src/hb-ot-glyf-table.hh        |  2 ++
+ src/hb-ot-hmtx-table.hh        |  3 +++
+ src/hb-ot-kern-table.hh        |  2 ++
+ src/hb-ot-layout-gdef-table.hh |  1 +
+ src/hb-ot-layout-gpos-table.hh |  2 ++
+ src/hb-ot-layout-gsub-table.hh |  1 +
+ src/hb-ot-post-table.hh        |  2 ++
+ 13 files changed, 36 insertions(+), 13 deletions(-)
+
+commit a84309afc8817cd386e555af21dfcdc03388b329
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 09:33:01 2018 -0700
+
+    [face] Use saved cmap in collect_unicodes() APIs
+
+ src/hb-face.cc | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+commit c624e18a24311c66737dde4ce515aa1eca892b94
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 09:19:20 2018 -0700
+
+    [OT] Move code around
+
+ src/hb-ot-layout-gsub-table.hh | 18 ------------------
+ src/hb-ot-layout.cc            | 23 +++++++++++++++++++++--
+ 2 files changed, 21 insertions(+), 20 deletions(-)
+
+commit 399909468204b76769857508e74f802d648ca0a5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 09:12:25 2018 -0700
+
+    [OT] Use relaxed ops for recursing into GSUB/GPOS lookups again
+
+ src/hb-ot-layout-gpos-table.hh |  4 ++--
+ src/hb-ot-layout-gsub-table.hh |  4 ++--
+ src/hb-ot-layout.cc            | 12 ++++++++++--
+ src/hb-ot-layout.hh            |  4 ++--
+ 4 files changed, 16 insertions(+), 8 deletions(-)
+
+commit d8c57e85d9981b4c7a11fae4f31100359574cf13
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 09:03:31 2018 -0700
+
+    [GDEF] Move code around
+
+ src/hb-ot-layout-gdef-table.hh | 118 +-----------------------------------
+ src/hb-ot-layout.cc            | 134
+ ++++++++++++++++++++++++++++++++++++++---
+ src/hb-ot-layout.hh            |  14 +----
+ 3 files changed, 128 insertions(+), 138 deletions(-)
+
+commit 453e0c60b1c87d2cd2527d6d2de673f65458a9fd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 01:30:52 2018 -0700
+
+    Add template keyword
+
+    I swear I have no idea why this is needed, but it is...
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c44b0caf0d0cddb7228dcec0b9d25bb62f641abc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 01:29:30 2018 -0700
+
+    Fixup
+
+ src/hb-ot-layout-gpos-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4096fbe487d90de04020e32e8487295ecd4d8836
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 01:25:54 2018 -0700
+
+    [ot-face] Port GDEF to unified table accelerator model as well
+
+ src/hb-ot-face.cc              | 108 ----------------------------------
+ src/hb-ot-face.hh              |   2 +-
+ src/hb-ot-layout-gdef-table.hh | 129
+ +++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.cc            |  14 ++++-
+ src/hb-ot-layout.hh            |   5 +-
+ 5 files changed, 147 insertions(+), 111 deletions(-)
+
+commit b929100f8782816c2621715f6c007ecefc419d83
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 01:15:47 2018 -0700
+
+    [ot-face] Unify GSUB/GPOS accelerators in the table accelerator
+    framework
+
+ src/hb-aat-layout.cc           |  4 +---
+ src/hb-ot-face.cc              | 40
+ ++--------------------------------------
+ src/hb-ot-face.hh              | 25 +++++++++++--------------
+ src/hb-ot-layout-gpos-table.hh |  2 +-
+ src/hb-ot-layout-gsub-table.hh |  6 +++---
+ src/hb-ot-layout-gsubgpos.hh   | 24 +++++++++++++-----------
+ src/hb-ot-layout.cc            | 33 +++++++++++++++++----------------
+ src/hb-ot-layout.hh            | 17 +++++++++++++++++
+ src/hb-ot-shape.cc             |  1 +
+ 9 files changed, 66 insertions(+), 86 deletions(-)
+
+commit 963413fc5454d92621ae83a8d9c9324e404b8166
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 00:47:55 2018 -0700
+
+    WIP
+
+ src/hb-ot-cmap-table.hh        |  1 -
+ src/hb-ot-face.hh              | 22 ----------------------
+ src/hb-ot-layout-gpos-table.hh |  2 ++
+ src/hb-ot-layout-gsub-table.hh |  2 ++
+ src/hb-ot-layout-gsubgpos.hh   | 31 ++++++++++++++++++++++++++++++-
+ src/hb-ot-layout.hh            | 18 +++++++++++++++++-
+ 6 files changed, 51 insertions(+), 25 deletions(-)
+
+commit e6cb9380651c753485f721bd3df523d03be41d91
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 00:21:29 2018 -0700
+
+    [ot-face] Unify accelerators and tables
+
+ src/hb-machinery.hh     |  4 ++--
+ src/hb-ot-cmap-table.hh |  3 ++-
+ src/hb-ot-face.cc       |  6 +++--
+ src/hb-ot-face.hh       | 58
+ +++++++++++++------------------------------------
+ src/hb-ot-font.cc       |  6 ++---
+ 5 files changed, 26 insertions(+), 51 deletions(-)
+
+commit 7f8b6fe67d64b41786edbf8650efb1c0deba573f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 00:07:12 2018 -0700
+
+    Minor
+
+ src/hb-ot-face.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 59bca0d2cb6010bc237afb2255ccda3b8dd0585d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 26 00:06:12 2018 -0700
+
+    [ot-font] Rename
+
+ src/hb-ot-face.hh | 12 ++++++------
+ src/hb-ot-font.cc | 24 ++++++++++++------------
+ 2 files changed, 18 insertions(+), 18 deletions(-)
+
+commit 1c48a7ef06b82ef9ca013066d1fb3c6fda82aa0c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 23:54:06 2018 -0700
+
+    [ot-font] Cache tables on face, not font
+
+ src/hb-ot-cmap-table.hh      |  1 +
+ src/hb-ot-face.cc            |  2 ++
+ src/hb-ot-face.hh            | 55 +++++++++++++++++++++++++++-----
+ src/hb-ot-font.cc            | 75
+ ++++----------------------------------------
+ src/hb-ot-layout-gsubgpos.hh |  1 +
+ src/hb-ot-layout.hh          |  1 -
+ 6 files changed, 58 insertions(+), 77 deletions(-)
+
+commit 71f8893eff56bff651e3df6288becc68ecea6cd1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 23:27:45 2018 -0700
+
+    [ot-font] Use init0
+
+ src/hb-ot-font.cc | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit f36ae6f8a82485bbf727f24dfd7da8f32002cad6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 23:19:34 2018 -0700
+
+    [ot-font] Make everything (cmap/metrics) lazy
+
+ src/hb-machinery.hh |  5 +++++
+ src/hb-ot-font.cc   | 51
+ ++++++++++++++++++++++++++-------------------------
+ 2 files changed, 31 insertions(+), 25 deletions(-)
+
+commit 62fc54725a3863473829f3a3748c9336e4dc0787
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 23:15:52 2018 -0700
+
+    [ot-font] Fallback vertical advance to UPEM
+
+    Used to be ascent+descent.  Whatever. This is more convenient for
+    upcoming changes.
+
+ src/hb-ot-font.cc                               | 2 +-
+ test/shaping/data/in-house/tests/vertical.tests | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit d950022c8ae3f85546272b38b187d6ed9f5ff16f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 23:06:37 2018 -0700
+
+    Add hb-ot-face.cc/hh
+
+ src/Makefile.sources |   2 +
+ src/hb-ot-face.cc    | 206
+ +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-face.hh    | 144 +++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.cc  | 172 ------------------------------------------
+ src/hb-ot-layout.hh  | 108 +--------------------------
+ src/hb-ot-math.cc    |   2 +-
+ src/hb-ot-var.cc     |   2 +-
+ 7 files changed, 355 insertions(+), 281 deletions(-)
+
+commit dae39c58fb63c2211e2842121bbe6d5b8b18651b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 22:44:39 2018 -0700
+
+    [face] Introduce character-map API
+
+    New API:
+    +hb_face_collect_unicodes
+    +hb_face_collect_variation_selectors
+    +hb_face_collect_variation_unicodes
+
+ docs/harfbuzz-sections.txt                      |  3 ++
+ src/hb-face.cc                                  | 61
+ ++++++++++++++++++++++++-
+ src/hb-face.h                                   | 19 ++++++++
+ src/hb-subset.cc                                | 53
+ ---------------------
+ src/hb-subset.h                                 | 15 ------
+ test/api/test-subset-codepoints.c               |  6 +--
+ test/fuzzing/hb-subset-get-codepoints-fuzzer.cc |  2 +-
+ 7 files changed, 86 insertions(+), 73 deletions(-)
+
+commit 66384db97c439a64d729f9206657d0b37ec0cb32
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 22:39:17 2018 -0700
+
+    Minor
+
+ src/hb-subset.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit c77ae40852aabb1698da9e8d488f75bae2f4e734
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 22:36:36 2018 -0700
+
+    Rename hb-*private.hh to hb-*.hh
+
+    Sorry for the noise, downstream custom builders.  Please adjust.
+
+ src/Makefile.sources                               | 75
+ +++++++++++-----------
+ src/check-includes.sh                              |  8 +--
+ src/dump-indic-data.cc                             |  2 +-
+ src/dump-khmer-data.cc                             |  2 +-
+ src/dump-myanmar-data.cc                           |  2 +-
+ src/dump-use-data.cc                               |  2 +-
+ src/gen-indic-table.py                             |  2 +-
+ src/gen-use-table.py                               |  2 +-
+ src/hb-aat-layout-ankr-table.hh                    |  2 +-
+ src/hb-aat-layout-bsln-table.hh                    |  2 +-
+ ...t-common-private.hh => hb-aat-layout-common.hh} |  8 +--
+ src/hb-aat-layout-feat-table.hh                    |  2 +-
+ src/hb-aat-layout-kerx-table.hh                    |  4 +-
+ src/hb-aat-layout-morx-table.hh                    |  6 +-
+ src/hb-aat-layout-trak-table.hh                    |  6 +-
+ src/hb-aat-layout.cc                               |  8 +--
+ src/{hb-aat-layout-private.hh => hb-aat-layout.hh} | 14 ++--
+ src/hb-aat-ltag-table.hh                           |  2 +-
+ src/{hb-atomic-private.hh => hb-atomic.hh}         |  8 +--
+ src/hb-blob.cc                                     |  4 +-
+ src/{hb-blob-private.hh => hb-blob.hh}             |  8 +--
+ src/hb-buffer-deserialize-json.hh                  |  2 +-
+ src/hb-buffer-deserialize-json.rl                  |  2 +-
+ src/hb-buffer-deserialize-text.hh                  |  2 +-
+ src/hb-buffer-deserialize-text.rl                  |  2 +-
+ src/hb-buffer-serialize.cc                         |  2 +-
+ src/hb-buffer.cc                                   |  4 +-
+ src/{hb-buffer-private.hh => hb-buffer.hh}         | 10 +--
+ src/hb-common.cc                                   |  4 +-
+ src/hb-coretext.cc                                 |  4 +-
+ src/hb-debug.hh                                    |  4 +-
+ src/hb-directwrite.cc                              |  4 +-
+ src/hb-dsalgs.hh                                   |  2 +-
+ src/hb-face.cc                                     |  8 +--
+ src/{hb-face-private.hh => hb-face.hh}             | 12 ++--
+ src/hb-fallback-shape.cc                           |  2 +-
+ src/hb-font.cc                                     |  6 +-
+ src/{hb-font-private.hh => hb-font.hh}             | 12 ++--
+ src/hb-ft.cc                                       |  6 +-
+ src/hb-glib.cc                                     |  6 +-
+ src/hb-gobject-enums.cc.tmpl                       |  2 +-
+ src/hb-gobject-structs.cc                          |  2 +-
+ src/hb-graphite2.cc                                |  2 +-
+ src/hb-icu.cc                                      |  6 +-
+ src/{hb-iter-private.hh => hb-iter.hh}             |  8 +--
+ src/{hb-machinery-private.hh => hb-machinery.hh}   | 12 ++--
+ src/hb-map.cc                                      |  2 +-
+ src/{hb-map-private.hh => hb-map.hh}               |  8 +--
+ src/{hb-mutex-private.hh => hb-mutex.hh}           |  8 +--
+ src/hb-null.hh                                     |  2 +-
+ src/{hb-object-private.hh => hb-object.hh}         | 14 ++--
+ src/{hb-open-file-private.hh => hb-open-file.hh}   |  8 +--
+ src/{hb-open-type-private.hh => hb-open-type.hh}   | 14 ++--
+ src/hb-ot-cmap-table.hh                            |  4 +-
+ src/hb-ot-color-cbdt-table.hh                      |  2 +-
+ src/hb-ot-color-colr-table.hh                      |  2 +-
+ src/hb-ot-color-cpal-table.hh                      |  2 +-
+ src/hb-ot-color-sbix-table.hh                      |  2 +-
+ src/hb-ot-color-svg-table.hh                       |  2 +-
+ src/hb-ot-color.cc                                 |  6 +-
+ src/hb-ot-font.cc                                  |  6 +-
+ src/hb-ot-glyf-table.hh                            |  4 +-
+ src/hb-ot-hdmx-table.hh                            |  2 +-
+ src/hb-ot-head-table.hh                            |  2 +-
+ src/hb-ot-hhea-table.hh                            |  2 +-
+ src/hb-ot-hmtx-table.hh                            |  2 +-
+ src/hb-ot-kern-table.hh                            |  2 +-
+ src/hb-ot-layout-base-table.hh                     |  4 +-
+ ...ut-common-private.hh => hb-ot-layout-common.hh} | 14 ++--
+ src/hb-ot-layout-gdef-table.hh                     |  4 +-
+ src/hb-ot-layout-gpos-table.hh                     |  2 +-
+ src/hb-ot-layout-gsub-table.hh                     |  2 +-
+ ...subgpos-private.hh => hb-ot-layout-gsubgpos.hh} | 14 ++--
+ src/hb-ot-layout-jstf-table.hh                     |  2 +-
+ src/hb-ot-layout.cc                                |  8 +--
+ src/{hb-ot-layout-private.hh => hb-ot-layout.hh}   | 16 ++---
+ src/hb-ot-map.cc                                   |  4 +-
+ src/{hb-ot-map-private.hh => hb-ot-map.hh}         |  8 +--
+ src/hb-ot-math-table.hh                            |  4 +-
+ src/hb-ot-math.cc                                  |  4 +-
+ src/hb-ot-maxp-table.hh                            |  2 +-
+ src/hb-ot-name-table.hh                            |  2 +-
+ src/hb-ot-os2-table.hh                             |  2 +-
+ src/hb-ot-os2-unicode-ranges.hh                    |  2 +-
+ src/hb-ot-post-macroman.hh                         |  2 +-
+ src/hb-ot-post-table.hh                            |  2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh         |  4 +-
+ src/hb-ot-shape-complex-arabic-win1256.hh          |  2 +-
+ src/hb-ot-shape-complex-arabic.cc                  |  6 +-
+ ...ic-private.hh => hb-ot-shape-complex-arabic.hh} | 10 +--
+ src/hb-ot-shape-complex-default.cc                 |  2 +-
+ src/hb-ot-shape-complex-hangul.cc                  |  2 +-
+ src/hb-ot-shape-complex-hebrew.cc                  |  2 +-
+ src/hb-ot-shape-complex-indic-machine.hh           |  2 +-
+ src/hb-ot-shape-complex-indic-machine.rl           |  2 +-
+ src/hb-ot-shape-complex-indic-table.cc             |  2 +-
+ src/hb-ot-shape-complex-indic.cc                   |  4 +-
+ ...dic-private.hh => hb-ot-shape-complex-indic.hh} | 12 ++--
+ src/hb-ot-shape-complex-khmer-machine.hh           |  2 +-
+ src/hb-ot-shape-complex-khmer-machine.rl           |  2 +-
+ src/hb-ot-shape-complex-khmer.cc                   |  4 +-
+ ...mer-private.hh => hb-ot-shape-complex-khmer.hh} | 10 +--
+ src/hb-ot-shape-complex-myanmar-machine.hh         |  2 +-
+ src/hb-ot-shape-complex-myanmar-machine.rl         |  2 +-
+ src/hb-ot-shape-complex-myanmar.cc                 |  2 +-
+ ...r-private.hh => hb-ot-shape-complex-myanmar.hh} | 10 +--
+ src/hb-ot-shape-complex-thai.cc                    |  2 +-
+ src/hb-ot-shape-complex-tibetan.cc                 |  2 +-
+ src/hb-ot-shape-complex-use-machine.hh             |  2 +-
+ src/hb-ot-shape-complex-use-machine.rl             |  2 +-
+ src/hb-ot-shape-complex-use-table.cc               |  2 +-
+ src/hb-ot-shape-complex-use.cc                     |  4 +-
+ ...x-use-private.hh => hb-ot-shape-complex-use.hh} | 10 +--
+ ...e-complex-private.hh => hb-ot-shape-complex.hh} | 12 ++--
+ src/hb-ot-shape-fallback.cc                        |  4 +-
+ ...fallback-private.hh => hb-ot-shape-fallback.hh} | 10 +--
+ src/hb-ot-shape-normalize.cc                       |  6 +-
+ ...rmalize-private.hh => hb-ot-shape-normalize.hh} |  8 +--
+ src/hb-ot-shape.cc                                 | 20 +++---
+ src/{hb-ot-shape-private.hh => hb-ot-shape.hh}     | 12 ++--
+ src/hb-ot-tag.cc                                   |  2 +-
+ src/hb-ot-var-avar-table.hh                        |  2 +-
+ src/hb-ot-var-fvar-table.hh                        |  2 +-
+ src/hb-ot-var-hvar-table.hh                        |  2 +-
+ src/hb-ot-var-mvar-table.hh                        |  2 +-
+ src/hb-ot-var.cc                                   |  4 +-
+ src/{hb-set-digest-private.hh => hb-set-digest.hh} |  8 +--
+ src/hb-set.cc                                      |  2 +-
+ src/{hb-set-private.hh => hb-set.hh}               |  8 +--
+ src/hb-shape-plan.cc                               | 10 +--
+ src/{hb-shape-plan-private.hh => hb-shape-plan.hh} | 10 +--
+ src/hb-shape.cc                                    | 12 ++--
+ ...hb-shaper-impl-private.hh => hb-shaper-impl.hh} | 16 ++---
+ src/hb-shaper.cc                                   |  6 +-
+ src/{hb-shaper-private.hh => hb-shaper.hh}         |  8 +--
+ src/hb-static.cc                                   |  8 +--
+ src/hb-string-array.hh                             |  2 +-
+ src/hb-subset-glyf.cc                              |  2 +-
+ src/hb-subset-glyf.hh                              |  2 +-
+ src/hb-subset-input.cc                             |  4 +-
+ src/hb-subset-plan.cc                              |  6 +-
+ src/hb-subset-plan.hh                              |  6 +-
+ src/hb-subset.cc                                   |  8 +--
+ src/{hb-subset-private.hh => hb-subset.hh}         | 10 +--
+ src/hb-ucdn.cc                                     |  6 +-
+ src/hb-unicode.cc                                  |  6 +-
+ src/{hb-unicode-private.hh => hb-unicode.hh}       |  8 +--
+ src/hb-uniscribe.cc                                |  6 +-
+ src/{hb-utf-private.hh => hb-utf.hh}               |  8 +--
+ src/{hb-vector-private.hh => hb-vector.hh}         |  8 +--
+ src/hb-warning.cc                                  |  6 +-
+ src/{hb-private.hh => hb.hh}                       | 12 ++--
+ src/main.cc                                        |  4 +-
+ src/test-buffer-serialize.cc                       |  2 +-
+ src/test-size-params.cc                            |  2 +-
+ src/test-unicode-ranges.cc                         |  2 +-
+ src/test-would-substitute.cc                       |  2 +-
+ src/test.cc                                        |  2 +-
+ test/api/test-common.c                             |  1 -
+ util/Makefile.am                                   |  4 +-
+ util/ansi-print.hh                                 |  3 +-
+ util/hb-subset.cc                                  |  2 +-
+ util/helper-cairo-ansi.hh                          |  2 +-
+ util/helper-cairo.hh                               |  2 +-
+ util/main-font-text.hh                             |  2 +-
+ util/options.hh                                    |  2 +-
+ util/shape-consumer.hh                             |  2 +-
+ util/view-cairo.hh                                 |  2 +-
+ 168 files changed, 452 insertions(+), 455 deletions(-)
+
+commit 82b12bcadd50c9e86bbe82623a1cbc0b4afdd237
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 22:07:17 2018 -0700
+
+    [unicode] Add HB_UNICODE_MAX
+
+    New API:
+    HB_UNICODE_MAX
+
+ docs/harfbuzz-sections.txt | 1 +
+ src/hb-ot-cmap-table.hh    | 8 ++------
+ src/hb-unicode.h           | 3 +++
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+commit b09a0336ca856a2b1040e7fabd5819b64749e308
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 22:04:39 2018 -0700
+
+    [cmap] More hb_auto_t<>(...)
+
+ src/hb-subset.cc | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+commit 28634db07e6ecbdb7e59ed8f989212272a97de86
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 21:23:43 2018 -0700
+
+    [cmap] Fix skipping gid0 in Format4 collect_unicodes()
+
+ src/hb-ot-cmap-table.hh | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+commit acce1fa3ea9707d0883cd66397fd187d3268905c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 21:15:39 2018 -0700
+
+    Use new hb_auto_t<> constructor with Coverage::Iter
+
+ src/hb-ot-layout-common-private.hh | 65
+ ++++++++++++++++++++++++--------------
+ src/hb-ot-layout-gsub-table.hh     | 30 ++++++------------
+ 2 files changed, 52 insertions(+), 43 deletions(-)
+
+commit ddea4d19cf6d64270e14418f02e7ff1f1b9458db
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 21:08:15 2018 -0700
+
+    Add 1-param passthrough constructor to hb_auto_t<>
+
+    And use.
+
+ src/hb-dsalgs.hh        | 1 +
+ src/hb-ot-cmap-table.hh | 7 +++----
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit c8cfb702e96bf4e89495fcc56f965c88bfa77dca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 16:14:32 2018 -0700
+
+    [cmap] Minor
+
+ src/hb-ot-cmap-table.hh | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+commit 1dcf5fb038e7c2d3d03a50c4cd9869a922f9adf7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 16:11:26 2018 -0700
+
+    [cmap Add hb_subset_collect_variation_unicodes()
+
+    To be moved to hb-face.h later.
+
+ src/hb-ot-cmap-table.hh | 59
+ +++++++++++++++++++++++++++++++++++++++++--------
+ src/hb-subset.cc        | 25 ++++++++++++++++++++-
+ src/hb-subset.h         | 10 +++++++--
+ 3 files changed, 82 insertions(+), 12 deletions(-)
+
+commit 4806b3800d77603c203e8bb2e88baeb2b3a14f05
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 15:56:07 2018 -0700
+
+    [cmap] Add hb_subset_collect_variation_selectors()
+
+    To be moved to hb-face later.
+
+ src/hb-ot-cmap-table.hh | 20 ++++++++++++++++----
+ src/hb-subset.cc        | 30 ++++++++++++++++++++++++++----
+ src/hb-subset.h         |  8 +++++++-
+ 3 files changed, 49 insertions(+), 9 deletions(-)
+
+commit 3336de24790ac1a12852ac2a3e2fff4d6bb19bc7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 15:41:25 2018 -0700
+
+    [cmap] Remove unused code
+
+ src/hb-ot-cmap-table.hh | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+commit 1becabe06c0c58aaf69a9ba641508e77a60f3451
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 15:37:56 2018 -0700
+
+    [cmap] Use bsearch to find subtables
+
+ src/hb-ot-cmap-table.hh                       | 5 +----
+ test/shaping/data/in-house/tests/fuzzed.tests | 2 +-
+ 2 files changed, 2 insertions(+), 5 deletions(-)
+
+commit 02fe03e09a3258e07d2d6749990f6d31dd2a8525
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 15:33:05 2018 -0700
+
+    [cmap] Factor out find_best_subtable
+
+ src/hb-ot-cmap-table.hh | 52
+ +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 31 insertions(+), 21 deletions(-)
+
+commit b41c43b4e112bfa38fef35694842f242c28a7da2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 15:25:03 2018 -0700
+
+    Minor
+
+ src/hb-ot-cmap-table.hh | 48
+ ++++++++++++++++++++++++++----------------------
+ 1 file changed, 26 insertions(+), 22 deletions(-)
+
+commit 7d382fa276f44b7b163e98d434cc79f958bf87fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 09:35:45 2018 -0700
+
+    [cmap] Implement collect_unicodes() for Format0/6/10
+
+ src/hb-ot-cmap-table.hh | 23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+commit bd0e542525d41d9ebe51cbcab8151d65eb984b2e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 09:33:30 2018 -0700
+
+    [cmap] Simplify collect_unicodes()
+
+    Don't use accelerator (almost).  Hooks up Format13 as well.
+
+ src/hb-ot-cmap-table.hh | 52
+ +++++++++++++++++++++++++++----------------------
+ 1 file changed, 29 insertions(+), 23 deletions(-)
+
+commit d60c465627d76fcfbeb37d6b8f9382f3b84ace6e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 08:47:06 2018 -0700
+
+    Rename get_all_codepoints() to collect_unicodes()
+
+ src/hb-ot-cmap-table.hh                         | 26
+ ++++++++++++-------------
+ src/hb-subset.cc                                |  6 +++---
+ src/hb-subset.h                                 |  4 ++--
+ test/api/test-subset-codepoints.c               | 18 ++++++++---------
+ test/fuzzing/hb-subset-get-codepoints-fuzzer.cc |  2 +-
+ 5 files changed, 28 insertions(+), 28 deletions(-)
+
+commit 531051b8b904cf4eb6a50bacebc11c2d85e40140
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 08:44:18 2018 -0700
+
+    [ot-font] Return char-not-found if mapped to gid 0
+
+    OpenType cmap table can use gid=0 to mean "not covered" to produce
+    more optimized cmap subtables.  Return false from get_nominal_glyph()
+    for those.  hb-ft already does this.
+
+ src/hb-ot-cmap-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit aadb2a9188f143126392c0b0f139326dcf7f9c8d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Aug 25 08:18:53 2018 -0700
+
+    Add face-builder
+
+    New API:
+    +hb_face_builder_create
+    +hb_face_builder_add_table
+
+ docs/harfbuzz-sections.txt |   5 +-
+ src/hb-face.cc             | 149
+ +++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-face.h              |  14 +++++
+ src/hb-subset-plan.cc      |   2 +-
+ src/hb-subset-plan.hh      |   2 +-
+ src/hb-subset-private.hh   |   7 ---
+ src/hb-subset.cc           | 129 ---------------------------------------
+ 7 files changed, 169 insertions(+), 139 deletions(-)
+
+commit 6cac9dc9ccb76945e9dfacafc169afad4a6e1e88
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 24 10:29:45 2018 -0700
+
+    [blob] Add as_bytes()
+
+ src/hb-blob-private.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 29a9a0883877c598413de78cd0c61f07bc393b2c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 24 10:24:45 2018 -0700
+
+    [sanitize] Document how sanitize machinery works
+
+ src/hb-machinery-private.hh | 62
+ +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+commit 142ac5a6be6088771e0ee4b135ba753c80036a9a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 24 10:07:49 2018 -0700
+
+    [serialize] Add copy_bytes() and copy_blob()
+
+ src/hb-dsalgs.hh            |  3 +++
+ src/hb-machinery-private.hh | 21 ++++++++++++++++++++-
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+commit 1c6b3693245d38103cab224d75262d45dc88c71c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 15 20:12:25 2018 -0700
+
+    [ot] Rename hb_ot_layout_t to hb_ot_face_data_t
+
+ src/hb-aat-layout.cc                 |  17 +-----
+ src/hb-ot-color.cc                   |   6 +--
+ src/hb-ot-layout-gpos-table.hh       |   6 +--
+ src/hb-ot-layout-gsub-table.hh       |   8 ++-
+ src/hb-ot-layout-gsubgpos-private.hh |   2 +-
+ src/hb-ot-layout-private.hh          |  12 ++---
+ src/hb-ot-layout.cc                  | 100
+ +++++++++++++++++------------------
+ src/hb-ot-math.cc                    |   2 +-
+ src/hb-ot-shape.cc                   |   5 +-
+ src/hb-ot-var.cc                     |   4 +-
+ 10 files changed, 71 insertions(+), 91 deletions(-)
+
+commit 27c32d8afbdf5b587b14f3b194f79882680348ba
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 22 11:36:39 2018 -0700
+
+    fixed "Fixed" number decoding
+
+ src/hb-cff-interp-common-private.hh    | 11 ++++++++++-
+ src/hb-cff-interp-cs-common-private.hh |  4 ++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+commit 811a651bbd3f1bda7ed8eaee9af8e9dbbc8f80de
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Aug 20 14:04:46 2018 -0700
+
+    fixed bugs with empty CFFIndex, fullset FDMap
+
+ src/hb-ot-cff-common-private.hh | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+commit 5cde2f55cd2f8917954f3a3f60bd571c86b3aa59
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 17 16:50:13 2018 -0700
+
+    drop hints from CFF & CFF2 Private
+
+ src/hb-cff-interp-dict-common-private.hh | 24 ++++++++++++++
+ src/hb-subset-cff1.cc                    | 53
+ +++++++++++++++++++++++++++---
+ src/hb-subset-cff2.cc                    | 55
+ +++++++++++++++++++++++++++++---
+ 3 files changed, 123 insertions(+), 9 deletions(-)
+
+commit cef75ea41a513a612a683bced27ced31761204b5
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 17 13:13:18 2018 -0700
+
+    Added CFF2 Subr nullifier
+
+    along with CFF2 charstring interpreter
+    factored out common code between CFF1 & CFF2 to CSInterpreter
+    moved fetch_op from Interpreter to InterpEnv
+    misc code clean up & bug fixes
+
+ src/Makefile.sources                     |  1 +
+ src/hb-cff-interp-common-private.hh      | 44 +++++++--------
+ src/hb-cff-interp-cs-common-private.hh   | 95
+ +++++++++++++++++++++++++++++--
+ src/hb-cff-interp-dict-common-private.hh |  3 +-
+ src/hb-cff1-interp-cs.hh                 | 82 ---------------------------
+ src/hb-cff2-interp-cs.hh                 | 97
+ ++++++++++++++++++++++++++++++++
+ src/hb-ot-cff-common-private.hh          |  4 ++
+ src/hb-ot-cff2-table.hh                  |  7 ++-
+ src/hb-subset-cff1.cc                    |  1 +
+ src/hb-subset-cff2.cc                    | 62 ++++++++++++++++++--
+ 10 files changed, 278 insertions(+), 118 deletions(-)
+
+commit f57d6bcbca276cec54d1e5308c308265e8e983b9
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 16 08:03:46 2018 -0700
+
+    renamed CFF::Index to CFF::CFFIndex
+
+    to avoid confusion with OT::Index
+
+ src/hb-ot-cff-common-private.hh | 38
+ +++++++++++++++++++-------------------
+ src/hb-ot-cff1-table.hh         |  4 ++--
+ src/hb-ot-cff2-table.hh         |  2 +-
+ src/hb-subset-cff2.cc           |  4 ++--
+ 4 files changed, 24 insertions(+), 24 deletions(-)
+
+commit c4ae426a3d3f9411b94d35745ca0e14677cd7bdb
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 16 00:59:46 2018 -0700
+
+    treat h/vstem the same as h/vstemhm
+
+ src/hb-cff1-interp-cs.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit e67bb3fbcf39385ea1db136aeca61291364fb75b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 16 00:25:57 2018 -0700
+
+    renamed OT::cff to OT::cff1 for consistency
+
+    along with HB_OT_TAG_cff1
+
+ src/hb-ot-cff1-table.hh | 14 +++++++-------
+ src/hb-subset-cff1.cc   | 16 ++++++++--------
+ src/hb-subset.cc        |  4 ++--
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+commit fdbfa1848b2f279c0f7a885bc1a985fa3375cfcd
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 16 00:13:09 2018 -0700
+
+    renamed CFF version 1 structs and sources to CFF1 from CFF
+
+    "CFF" is used for shared structs & sources between CFF1 & CFF2
+    except OT:cff is for CFF version 1 table
+
+ src/Makefile.sources                              |   8 +-
+ src/{hb-cff-interp-cs.hh => hb-cff1-interp-cs.hh} |  22 ++--
+ src/{hb-ot-cff-table.hh => hb-ot-cff1-table.hh}   | 150
+ +++++++++++-----------
+ src/hb-ot-font.cc                                 |   2 +-
+ src/{hb-subset-cff.cc => hb-subset-cff1.cc}       |  86 ++++++-------
+ src/{hb-subset-cff.hh => hb-subset-cff1.hh}       |   8 +-
+ src/hb-subset.cc                                  |   2 +-
+ 7 files changed, 139 insertions(+), 139 deletions(-)
+
+commit 867f68bd8a74634ac6220bd76c8bafe3e2226041
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 15:53:50 2018 -0700
+
+    fix build attempt ^7
+
+ src/hb-subset-cff2.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 685db67bb07505729fdb997129ffd068bbe3c40d
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 15:45:17 2018 -0700
+
+    fix build attempt ^6
+
+ src/hb-subset-cff2.cc | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 2810caafeb9a621d53653f454dab0fa3e7f5c4a3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 15:30:24 2018 -0700
+
+    fix build attempt ^5
+
+ src/hb-subset-cff2.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 25b8310b2a3e074c9d1d723ab6d10a29f8d189be
+Merge: 7aa23f35 22defe09
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 15:00:55 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 7aa23f3597e4783b88ad526021cc4cafc05395f2
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 15:00:32 2018 -0700
+
+    fix build attempt ^4
+
+ src/hb-cff-interp-cs.hh | 10 +++++-----
+ src/hb-subset-cff.cc    |  2 +-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+commit 270452a44653773b3dc584729ec438ff922e2739
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 13:15:08 2018 -0700
+
+    fix build attempt ^3
+
+ src/hb-cff-interp-common-private.hh    | 2 --
+ src/hb-cff-interp-cs-common-private.hh | 1 +
+ src/hb-cff-interp-cs.hh                | 1 +
+ src/hb-subset-cff.cc                   | 2 +-
+ 4 files changed, 3 insertions(+), 3 deletions(-)
+
+commit c234839f25e68700c3489c55fda2773f2e00eecb
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 13:04:43 2018 -0700
+
+    fix build attempt ^2
+
+ src/hb-cff-interp-common-private.hh      | 2 ++
+ src/hb-cff-interp-cs-common-private.hh   | 6 +++---
+ src/hb-cff-interp-cs.hh                  | 6 +++---
+ src/hb-cff-interp-dict-common-private.hh | 6 +++---
+ src/hb-subset-cff.cc                     | 6 +++---
+ 5 files changed, 14 insertions(+), 12 deletions(-)
+
+commit eab07e713a67da2c5b368c59808f7e2db1cf0b0b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 12:15:55 2018 -0700
+
+    fix build
+
+ src/Makefile.sources | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 633ce88de93f5c565ee7fb8acdbd93c57779524b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 15 12:00:19 2018 -0700
+
+    CFF Subrs subsetting
+
+    Unreferenced subroutines are nullified (not removed) in a subset font
+
+    Separate Interpreter struct from hb-ot-cff-common-private.hh in a
+    set of four header files, augmented for CharString (CS):
+    hb-cff-interp-common-private.hh
+    hb-cff-interp-dict-common-private.hh
+    hb-cff-interp-cs-common-private.hh
+    hb-cff-interp-cs.hh
+
+    Interpreter runtime is separated off as a new struct InterpEnv
+    sub-classed differently for Dict and CharString (CS)
+
+ src/Makefile.sources                     |   8 +-
+ src/hb-cff-interp-common-private.hh      | 581
+ +++++++++++++++++++++++++++++++
+ src/hb-cff-interp-cs-common-private.hh   | 174 +++++++++
+ src/hb-cff-interp-cs.hh                  | 282 +++++++++++++++
+ src/hb-cff-interp-dict-common-private.hh | 183 ++++++++++
+ src/hb-ot-cff-common-private.hh          | 562
+ ++----------------------------
+ src/hb-ot-cff-table.hh                   | 165 ++++-----
+ src/hb-ot-cff2-table.hh                  | 147 ++++----
+ src/hb-subset-cff-common-private.hh      |  83 +++++
+ src/hb-subset-cff.cc                     | 118 +++++--
+ src/hb-subset-cff2.cc                    |  38 +-
+ 11 files changed, 1585 insertions(+), 756 deletions(-)
+
+commit 22defe0965adddaa09eebc13df7fa6c64e2abba3
+Author: Emil A Eklund <eae@chromium.org>
+Date:   Tue Aug 14 14:47:20 2018 -0700
+
+    Add guard around free_static_C_locale
+
+    Add HB_USE_ATEXIT guard around free_static_C_locale missed by previous
+    commit.
+
+ src/hb-common.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7112c6413ca7a1773847fe258145cc5162420953
+Author: Emil A Eklund <eae@chromium.org>
+Date:   Tue Aug 14 13:50:24 2018 -0700
+
+    Guard free_static function definitions with macro
+
+    Add HB_USE_ATEXIT macros around free_static function definitions to
+    avoid unused function compiler warnings/errors.
+
+ src/hb-ft.cc      | 5 ++++-
+ src/hb-glib.cc    | 3 ++-
+ src/hb-icu.cc     | 3 ++-
+ src/hb-ot-font.cc | 3 ++-
+ src/hb-shape.cc   | 4 +++-
+ src/hb-shaper.cc  | 3 ++-
+ 6 files changed, 15 insertions(+), 6 deletions(-)
+
+commit 63be5dcdde61275822d931b2924425478bc1dac1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 14 10:59:34 2018 -0700
+
+    1.8.8
+
+ NEWS             | 18 ++++++++++++++++++
+ configure.ac     |  2 +-
+ src/hb-version.h |  4 ++--
+ 3 files changed, 21 insertions(+), 3 deletions(-)
+
+commit c9a22fa124310c98c73b8d7b495ed354542a75de
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 13 17:02:21 2018 -0700
+
+    [icu] Pass normalizer instance down as user_data
+
+ src/hb-icu.cc | 23 +++++++++--------------
+ 1 file changed, 9 insertions(+), 14 deletions(-)
+
+commit f0ef096b8cab33aa9e26edba9b15696bf907e268
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 13 10:30:41 2018 -0700
+
+    Don't add reference in get_unicode_funcs() functions
+
+    Users don't expect a new reference returned from a get() function.
+    Indeed, all users of that API I foud where NOT destroying the
+    reference.
+    Just change the implementations to NOT return a reference.
+
+    This applies to the following APIs:
+    hb_unicode_funcs_get_default()
+    hb_glib_get_unicode_funcs()
+    hb_icu_get_unicode_funcs()
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1134
+
+ src/hb-buffer.cc | 3 +--
+ src/hb-glib.cc   | 2 +-
+ src/hb-icu.cc    | 2 +-
+ src/hb-ucdn.cc   | 2 +-
+ 4 files changed, 4 insertions(+), 5 deletions(-)
+
+commit 9bbd1cdf068635f4a737f1fc9ab54ba075601a5d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 18:20:53 2018 -0700
+
+    [uniscribe] Use lazy loader
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1129
+
+ src/hb-uniscribe.cc | 56
+ +++++++++++++++++++++++++++--------------------------
+ 1 file changed, 29 insertions(+), 27 deletions(-)
+
+commit 266368993625e0cfb6eef9188f8b9aa29fb97391
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 18:10:59 2018 -0700
+
+    Another clang bot fix
+
+ src/hb-shape.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 989e71a982658145f28f83f2111bdab9561f3db0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 17:47:59 2018 -0700
+
+    Silence clang
+
+ src/hb-machinery-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6750ec692cdd682bd33cb1c37b137cf3bb641d43
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 17:42:16 2018 -0700
+
+    [lazy] Use for C_locale
+
+ src/hb-common.cc | 60
+ ++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 30 insertions(+), 30 deletions(-)
+
+commit 747d2564e6bdcc15cf6a197e543fb732924159c5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 17:32:10 2018 -0700
+
+    [lazy] Port more
+
+ src/hb-machinery-private.hh |  1 -
+ src/hb-shaper.cc            | 78
+ ++++++++++++++++++++-------------------------
+ src/hb-uniscribe.cc         |  3 +-
+ 3 files changed, 37 insertions(+), 45 deletions(-)
+
+commit 7bd508a0c4ce426f474bfcc729cb39207dd1f7b4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 17:19:55 2018 -0700
+
+    [lazy] Rename free()
+
+ src/hb-ft.cc                | 4 ++--
+ src/hb-glib.cc              | 2 +-
+ src/hb-icu.cc               | 2 +-
+ src/hb-machinery-private.hh | 4 ++--
+ src/hb-ot-font.cc           | 2 +-
+ src/hb-shape.cc             | 6 +++---
+ src/hb-ucdn.cc              | 2 +-
+ 7 files changed, 11 insertions(+), 11 deletions(-)
+
+commit a3b97db910662e26bafe6e6bc1c36b437f4ed931
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 17:14:32 2018 -0700
+
+    [lazy] Port more to it
+
+ src/hb-shape.cc | 75
+ +++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 38 insertions(+), 37 deletions(-)
+
+commit 6901090945d7e16102f3a2b168465434032b9a09
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:57:06 2018 -0700
+
+    [lazy] Make hb_lazy_loader_t<> more usable
+
+ src/hb-ft.cc                |  7 +++---
+ src/hb-machinery-private.hh | 57
+ +++++++++++++++++++++++++++------------------
+ 2 files changed, 37 insertions(+), 27 deletions(-)
+
+commit bb905e9afcc3eb28a22ba78c09e661a814d04c1f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:40:08 2018 -0700
+
+    [lazy] Minor
+
+ src/hb-machinery-private.hh | 36 ++++++++++++++++++------------------
+ src/hb-ot-font.cc           |  8 ++++----
+ 2 files changed, 22 insertions(+), 22 deletions(-)
+
+commit 3945cd78a96bdd287e203a0261bac490df1314b0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:33:48 2018 -0700
+
+    Minor
+
+ src/hb-machinery-private.hh | 4 ----
+ 1 file changed, 4 deletions(-)
+
+commit c21a1b95dffedb6ed66b384f4adf07e6d05d4b9f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:30:39 2018 -0700
+
+    [icu] Use get_relaxed for normalizer access
+
+    We've had the proper barriers already.  No need for more with
+    every access.
+
+ src/hb-icu.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 125fefa2a6b23cf7eb4559904b23aff3731d5dba
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:29:41 2018 -0700
+
+    [icu] Fix for breakage after recent change
+
+ src/hb-icu.cc | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+commit 53442be1edc73993bdcaffc4b895c07f1ea03ba0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:20:11 2018 -0700
+
+    [lazy] Use for ft_library
+
+ src/hb-ft.cc                | 61
+ ++++++++++++++++++++++-----------------------
+ src/hb-glib.cc              |  2 +-
+ src/hb-icu.cc               |  2 +-
+ src/hb-machinery-private.hh |  2 +-
+ src/hb-ot-font.cc           |  2 +-
+ src/hb-ucdn.cc              |  2 +-
+ 6 files changed, 35 insertions(+), 36 deletions(-)
+
+commit 7a8d480378af4094645dfb1527a61a94b4786b54
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 16:00:13 2018 -0700
+
+    [lazy] Add .free()
+
+ src/hb-ft.cc                | 2 +-
+ src/hb-glib.cc              | 2 +-
+ src/hb-icu.cc               | 2 +-
+ src/hb-machinery-private.hh | 4 ++++
+ src/hb-ot-font.cc           | 2 +-
+ src/hb-ucdn.cc              | 2 +-
+ 6 files changed, 9 insertions(+), 5 deletions(-)
+
+commit c7ca30a5337cb660e650d51ddd17d389909357c2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 13:46:53 2018 -0700
+
+    [ot/ft] Port font_funcs statis to lazy-loader
+
+ src/hb-ft.cc                | 56
+ ++++++++++++++++++++++-----------------------
+ src/hb-machinery-private.hh | 14 ++++++++++++
+ src/hb-ot-font.cc           | 49 +++++++++++++++++----------------------
+ 3 files changed, 62 insertions(+), 57 deletions(-)
+
+commit cb3fc3685c03c8ed07bcf05188f5d6c582fd5aaa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 13:39:01 2018 -0700
+
+    [ucdn/glib/icu] Port unicode_funcs statics to lazy-loader
+
+ src/hb-glib.cc              | 50 ++++++++++++++++++--------------------
+ src/hb-icu.cc               | 59
+ ++++++++++++++++-----------------------------
+ src/hb-machinery-private.hh | 28 ++++++++++++++++-----
+ src/hb-ucdn.cc              | 51 +++++++++++++++++----------------------
+ 4 files changed, 88 insertions(+), 100 deletions(-)
+
+commit 1b6b481262465ae1865c66c4d499b4b2c8d297fb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 13:16:40 2018 -0700
+
+    [lazy] Allow calling fini() multiple times
+
+ src/hb-machinery-private.hh | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+commit 918ad9f5d9b85384f24157523272a4ffc1927d16
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 13:12:29 2018 -0700
+
+    [lazy] More
+
+ src/hb-machinery-private.hh | 45
+ +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 37 insertions(+), 8 deletions(-)
+
+commit 5abdf5eebadf9a4fbd50c1a893c9654de74d22ac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 12:40:24 2018 -0700
+
+    [lazy] More shuffle
+
+ src/hb-machinery-private.hh | 80
+ +++++++++++++++++++--------------------------
+ 1 file changed, 34 insertions(+), 46 deletions(-)
+
+commit 5d9863be6ecf873033cbab732207dd420f3866e7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 12:27:47 2018 -0700
+
+    Minor
+
+ src/hb-machinery-private.hh | 6 ++++--
+ src/hb-ot-layout-private.hh | 2 +-
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+commit f9a3eab81008c01a458d16f274b1a0eaaae00e7c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 12:21:56 2018 -0700
+
+    Add explicit_operator
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1127
+
+ src/hb-iter-private.hh |  2 +-
+ src/hb-private.hh      | 15 ++++++++++++++-
+ 2 files changed, 15 insertions(+), 2 deletions(-)
+
+commit 470acb6c322fc64556d59847d829d95caa2d51e6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 12 12:09:20 2018 -0700
+
+    Rename
+
+ src/hb-machinery-private.hh | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+commit 39607dc98e433ef577c1de0f309ce40fc40529be
+Author: Martin Hosken <martin_hosken@sil.org>
+Date:   Thu Aug 9 15:16:32 2018 +0700
+
+    Support _ in feature ids
+
+ src/hb-common.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a3a8c85b027779365bb33e2063221b4650fbac3b
+Merge: 145f371d 652cd45c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 10 13:41:42 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 145f371d71965b86635025c73117db0e24f2df75
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 10 13:07:53 2018 -0700
+
+    fixed TRACE build failure
+
+ src/hb-ot-cff-common-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a97ed342d18bdb262400c8ab6501df110fe4e18f
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 10 12:55:22 2018 -0700
+
+    fixed inclusion of excluded Private & local Subrs
+
+    It was bloating a multi-FD subset font unnecessarily
+    defined a wrapper struct FDMap for fdmap
+
+ src/hb-ot-cff-common-private.hh     | 34 ++++++++++++++++++++-----
+ src/hb-subset-cff-common-private.cc |  6 ++---
+ src/hb-subset-cff-common-private.hh |  4 +--
+ src/hb-subset-cff.cc                | 48
+ +++++++++++++++++++----------------
+ src/hb-subset-cff2.cc               | 50
+ ++++++++++++++++++++-----------------
+ 5 files changed, 87 insertions(+), 55 deletions(-)
+
+commit 64c541226457907ec1801a5766050ee64feb67e8
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 10 11:07:07 2018 -0700
+
+    Added CFF support
+
+    Added sources hb-ot-cff-table.hh, hb-subset-cff.cc & hh
+    Templatized Index because CFF uses 16-bit count while CFF2 uses 32-bit
+    Misc code cleanup & bug fixes
+
+ src/Makefile.sources                |   9 +-
+ src/hb-ot-cff-common-private.hh     | 477 ++++++++++++-------
+ src/hb-ot-cff-table.hh              | 919
+ ++++++++++++++++++++++++++++++++++++
+ src/hb-ot-cff2-table.hh             | 235 ++++-----
+ src/hb-ot-font.cc                   |   1 +
+ src/hb-subset-cff-common-private.cc |   6 +-
+ src/hb-subset-cff-common-private.hh |   4 +-
+ src/hb-subset-cff.cc                | 560 ++++++++++++++++++++++
+ src/hb-subset-cff.hh                |  38 ++
+ src/hb-subset-cff2.cc               | 104 ++--
+ src/hb-subset.cc                    |   4 +
+ 11 files changed, 1991 insertions(+), 366 deletions(-)
+
+commit 652cd45c650b1cdce2585dcee614e5a9cdda530c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 01:02:02 2018 -0700
+
+    [coretext] Another try
+
+ src/hb-coretext.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3f3585ca1406edd74138f78739612c167ab57913
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 00:58:17 2018 -0700
+
+    Fix coretext build (hopefully)
+
+ src/hb-coretext.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit aa3b6017ed71fc251522ff1bedcdae965b4c1c1c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 00:56:28 2018 -0700
+
+    Revert "[iter] Make operator bool explicit"
+
+    This reverts commit 66920a6bace7c54c8166c4ed938b6ffc5fabcf2b.
+
+    Some of our bots (Oracle Studio and Apple gcc 4.2) do not allow
+    explicit except for constructors.
+
+    https://github.com/harfbuzz/harfbuzz/issues/1127
+
+ src/hb-iter-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e1a2354220c369bd5a62d255acc42c60cd14c473
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 00:53:25 2018 -0700
+
+    [atomic] More
+
+ src/hb-atomic-private.hh | 2 --
+ src/hb-object-private.hh | 7 +++++--
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+commit f1f4b45ac3d228a6b11e33357725de065e2ba2be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 00:28:40 2018 -0700
+
+    Fix lazy_loader fini()
+
+    Was creating object even if wasn't there.
+
+ src/hb-machinery-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1f7380944df9aa81cd48a4764c763d692533c4a6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 9 00:22:37 2018 -0700
+
+    [atomic] Add hb_atomic_ptr_t<> and port all uses
+
+    Found and fixed a couple bugs.
+
+    Found a couple multithreading issues.  Marked them with "XXX-MT-bug".
+
+ src/hb-atomic-private.hh          | 34 +++++++++++++++++++++++++++++++---
+ src/hb-common.cc                  | 34 ++++++++++++++++++----------------
+ src/hb-face-private.hh            |  3 ++-
+ src/hb-face.cc                    |  6 +++---
+ src/hb-font.cc                    |  2 +-
+ src/hb-ft.cc                      | 22 ++++++++++++----------
+ src/hb-glib.cc                    | 11 ++++++-----
+ src/hb-graphite2.cc               | 16 +++++++++-------
+ src/hb-icu.cc                     | 22 ++++++++++++----------
+ src/hb-machinery-private.hh       | 17 +++++++++--------
+ src/hb-object-private.hh          | 29 +++++++++++++++--------------
+ src/hb-ot-font.cc                 | 11 ++++++-----
+ src/hb-ot-layout-private.hh       |  2 +-
+ src/hb-ot-post-table.hh           |  9 +++++----
+ src/hb-ot-shape-complex-arabic.cc |  9 +++++----
+ src/hb-shape-plan.cc              | 19 +++++++++++--------
+ src/hb-shape.cc                   | 11 ++++++-----
+ src/hb-shaper-impl-private.hh     |  2 +-
+ src/hb-shaper-private.hh          | 16 +++++++++-------
+ src/hb-shaper.cc                  | 18 ++++++++++--------
+ src/hb-ucdn.cc                    | 11 ++++++-----
+ src/hb-uniscribe.cc               | 14 +++++++-------
+ 22 files changed, 185 insertions(+), 133 deletions(-)
+
+commit 6e42f4c53ff52cc242051e80600e19513136f6d1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:51:35 2018 -0700
+
+    [atomic] Remove hb_atomic_int_impl_t now that it's always int
+
+ src/hb-atomic-private.hh | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+commit 1227a9e5a5befffa688c1cce141533fd80144d14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:45:49 2018 -0700
+
+    [atomic] Unify typedef
+
+    Removes volatile from fallback implementation.  That was handwavy
+    anyway.
+
+ src/hb-atomic-private.hh | 22 ++++++++--------------
+ 1 file changed, 8 insertions(+), 14 deletions(-)
+
+commit 5cd1888c9dcb8b32bcfe08be38bdd13fd8a09b5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:43:53 2018 -0700
+
+    [atomic] Change Mac atomic int type to int
+
+    If ever int is not 32bit, we'll fix this...
+
+ src/hb-atomic-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e1de86eac188e804c6737fcad66ae09cf25ef221
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:42:33 2018 -0700
+
+    [atomic] Change Windows atomic int type to int
+
+ src/hb-atomic-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit aee2d10b2bf09814b32bccdecd4c3fbebafc542e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:40:10 2018 -0700
+
+    [atomic] Change Solaris atomic int to signed
+
+ src/hb-atomic-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit b6fdcf4f8bd09e065c767939125861c9dc8ff18f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 21:54:08 2018 -0700
+
+    1.8.7
+
+ NEWS             | 6 ++++++
+ RELEASING.md     | 3 +++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 4 files changed, 12 insertions(+), 3 deletions(-)
+
+commit 51ffc3e65aacbece63995be99e2bc20538e3eb75
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 22:01:04 2018 -0700
+
+    Fix previous commit to use atomic operations
+
+ src/hb-machinery-private.hh | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+commit 883957688cc4aa4335e5131a60b3ac3b53290726
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 8 21:42:18 2018 -0700
+
+    Fix assertion failure
+
+    https://bugzilla.mozilla.org/show_bug.cgi?id=1476334
+
+ src/hb-machinery-private.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit e49a38b20e82e50bca96751470e945cbe0524880
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 7 09:55:42 2018 -0700
+
+    1.8.6
+
+ NEWS             | 15 +++++++++++++++
+ configure.ac     |  2 +-
+ src/hb-font.cc   |  6 +++---
+ src/hb-font.h    |  4 ++--
+ src/hb-version.h |  4 ++--
+ 5 files changed, 23 insertions(+), 8 deletions(-)
+
+commit b0ff79acd804e47a2a3db73746cf9c6dc986950a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 7 09:52:06 2018 -0700
+
+    Add +hb_font_get_glyph_advances_for_direction
+
+    New API:
+    +hb_font_get_glyph_advances_for_direction
+
+ docs/harfbuzz-sections.txt |  1 +
+ src/hb-font-private.hh     | 12 ++++++++++++
+ src/hb-font.cc             | 20 ++++++++++++++++++++
+ src/hb-font.h              |  8 ++++++++
+ 4 files changed, 41 insertions(+)
+
+commit 28e2f467e1c7dd5e82d105efa8c4580dbfc93960
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 7 09:47:00 2018 -0700
+
+    Actually add hb_font_get_glyph_[hv]_advances
+
+    New API:
+    +hb_font_get_glyph_h_advances
+    +hb_font_get_glyph_v_advances
+
+ src/hb-font.cc | 37 +++++++++++++++++++++++++++++++++++++
+ src/hb-font.h  | 15 +++++++++++++++
+ 2 files changed, 52 insertions(+)
+
+commit 996775191a3fdeeeaee80e3123ef2240e6390b3d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 7 09:44:01 2018 -0700
+
+    Minor
+
+ src/hb-font-private.hh | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit 3d7c555a19ca0725c386aa6da648ecf2ae50fc19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Aug 7 09:37:52 2018 -0700
+
+    Remove get_advances_nil and alias it to get_advances_default
+
+ src/hb-font.cc | 36 ++----------------------------------
+ 1 file changed, 2 insertions(+), 34 deletions(-)
+
+commit 66920a6bace7c54c8166c4ed938b6ffc5fabcf2b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 15:32:13 2018 -0700
+
+    [iter] Make operator bool explicit
+
+    We would need to write:
+
+      for (Iter<T> it (...); bool (t); t++)
+
+    instead of:
+
+      for (Iter<T> it (...); t; t++)
+
+    But I think it's an improvement in code readability in the long term.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1127
+
+ src/hb-iter-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 161ece4c3097096f355dc5ea514320a8dc678bea
+Merge: e8d695eb 79e21984
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Aug 6 11:23:50 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit e8d695ebaa4b5d36d907042fb6930244e87b1e29
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Aug 6 11:13:06 2018 -0700
+
+    removed CMakeCache.txt
+
+ build/CMakeCache.txt | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 9fae33b9f3fd7fce816c3db71089db4ce0c82d4c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Aug 6 10:44:12 2018 -0700
+
+    Silence Codacy
+
+ build/CMakeCache.txt                | 1 +
+ src/hb-subset-cff-common-private.cc | 8 +++++---
+ src/hb-subset-cff2.cc               | 4 +++-
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+commit 5561b818498431adb52f958d1e9589620f0e6539
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Aug 6 10:04:53 2018 -0700
+
+    subset FDSelect and FDArray
+
+    Added a set of sources hb-subset-cff-common-private.cc & .hh for
+    FDSelect subseting code.
+    Added FDSelect format 4 (CFF2 only) support. Shared its implementation
+    with format 3 as a template.
+
+ src/Makefile.sources                |   2 +
+ src/hb-ot-cff-common-private.hh     | 130 ++++++++++++++++-------
+ src/hb-ot-cff2-table.hh             |  71 ++++++++++++-
+ src/hb-subset-cff-common-private.cc | 200
+ ++++++++++++++++++++++++++++++++++++
+ src/hb-subset-cff-common-private.hh |  54 ++++++++++
+ src/hb-subset-cff2.cc               |  71 ++++++++++---
+ 6 files changed, 476 insertions(+), 52 deletions(-)
+
+commit 79e21984b13bdb879f3007ba9a97fde47df340d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 09:45:17 2018 -0700
+
+    Add batch advance width callback function
+
+    New API:
+    +hb_font_funcs_set_glyph_h_advances_func
+    +hb_font_funcs_set_glyph_v_advances_func
+    +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
+
+ docs/harfbuzz-sections.txt |   6 +
+ src/hb-font-private.hh     |  41 +++++--
+ src/hb-font.cc             | 299
+ +++++++++++++++++++++++++++------------------
+ src/hb-font.h              |  53 ++++++--
+ src/hb-ot-shape.cc         |   3 +-
+ 5 files changed, 255 insertions(+), 147 deletions(-)
+
+commit 9533364cc3a8cccbae793de1873a727de73f64d5
+Author: Koji Ishii <kojii@chromium.org>
+Date:   Wed Aug 1 13:01:08 2018 +0900
+
+    batchwidth
+
+ src/hb-font-private.hh | 13 +++++++++++++
+ src/hb-font.cc         | 37 +++++++++++++++++++++++++++++++++++++
+ src/hb-font.h          | 15 +++++++++++++++
+ src/hb-ot-shape.cc     |  4 ++--
+ 4 files changed, 67 insertions(+), 2 deletions(-)
+
+commit b912fbea17c50e229977345012227810ed7641e9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 06:30:12 2018 -0700
+
+    Remove most uses of direct comparison to Null objects
+
+ src/hb-ot-glyf-table.hh                    | 6 +++---
+ src/hb-ot-head-table.hh                    | 4 ++--
+ src/hb-ot-layout-gdef-table.hh             | 1 +
+ src/hb-ot-layout-gsubgpos-private.hh       | 1 +
+ src/hb-ot-layout.cc                        | 6 +++---
+ src/hb-ot-math-table.hh                    | 2 ++
+ src/hb-ot-math.cc                          | 2 +-
+ src/hb-ot-shape-complex-arabic-fallback.hh | 3 ++-
+ src/hb-ot-var-fvar-table.hh                | 2 ++
+ src/hb-ot-var.cc                           | 2 +-
+ src/hb-subset.cc                           | 2 +-
+ src/main.cc                                | 2 +-
+ 12 files changed, 20 insertions(+), 13 deletions(-)
+
+commit 3506672ce9d8685ce4e113716b0d06adbc7981b7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 06:17:48 2018 -0700
+
+    Port _nil objects to Null() machinery
+
+    Finally, unified!
+
+ src/hb-blob-private.hh                     |  1 +
+ src/hb-blob.cc                             | 29 ++++++-------
+ src/hb-buffer-private.hh                   |  4 +-
+ src/hb-buffer.cc                           | 44 ++++++++++----------
+ src/hb-face-private.hh                     |  6 +--
+ src/hb-face.cc                             |  5 ++-
+ src/hb-font-private.hh                     | 10 +++--
+ src/hb-font.cc                             | 66
+ ++++++++++++++++--------------
+ src/hb-null.hh                             | 11 ++++-
+ src/hb-ot-shape-complex-arabic-fallback.hh | 11 +++--
+ src/hb-shape-plan-private.hh               |  1 +
+ src/hb-shape-plan.cc                       | 50 +++++++++++-----------
+ src/hb-unicode-private.hh                  |  7 ++--
+ src/hb-unicode.cc                          |  5 ++-
+ 14 files changed, 137 insertions(+), 113 deletions(-)
+
+commit 1abd427acfb7229b8607646bdde59f29306b86e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 05:53:35 2018 -0700
+
+    [BASE] Rename horzi/vert to h/v
+
+ src/hb-ot-layout-base-table.hh | 68
+ +++++++++++++++++++++---------------------
+ 1 file changed, 34 insertions(+), 34 deletions(-)
+
+commit da48aca1be89efbb8b3ca4471f542aa54aff17c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 05:52:12 2018 -0700
+
+    [BASE] Misc fixes
+
+    The code was badly broken.  In better shape now, but still, needs
+    a full review before ever working.
+
+ src/hb-ot-layout-base-table.hh | 163
+ +++++++++++++++++------------------------
+ 1 file changed, 68 insertions(+), 95 deletions(-)
+
+commit f9cfa5cb0e70203279e74fb6adb0cd4570238ff8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 05:29:15 2018 -0700
+
+    Change null-pool specialization to min_size again
+
+ src/hb-null.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 25147ff8086ab65995fe046cfdf8007604de6962
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 05:01:52 2018 -0700
+
+    Move Null system to hb-null.hh
+
+ src/Makefile.sources |  1 +
+ src/hb-null.hh       | 97
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-private.hh    | 65 +----------------------------------
+ 3 files changed, 99 insertions(+), 64 deletions(-)
+
+commit f800368df33e7ec15c3e77bdb9f4b464899322d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 04:58:34 2018 -0700
+
+    Remove unused macros
+
+ src/hb-object-private.hh | 1 -
+ src/hb-vector-private.hh | 1 -
+ 2 files changed, 2 deletions(-)
+
+commit 19e0091299f06856002c702792b448b06da637a8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 04:54:31 2018 -0700
+
+    Minor
+
+ src/hb-private.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 37be774af921812018f723521b90f2ab54f661c5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 04:51:38 2018 -0700
+
+    Minor
+
+ src/hb-private.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit e1acff806b469e58f568bf5ad6ba578207821e87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 04:42:46 2018 -0700
+
+    Move hb_vector_t to hb-vector-private.hh
+
+ src/Makefile.sources     |   1 +
+ src/hb-dsalgs.hh         | 297
+ -----------------------------------------------
+ src/hb-object-private.hh | 109 ++++++++++++++++-
+ src/hb-vector-private.hh | 239 ++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 346 insertions(+), 300 deletions(-)
+
+commit be336dadc07460a53de51be32dd5d1f218b398b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Aug 6 04:32:51 2018 -0700
+
+    Move some more code around
+
+ src/hb-dsalgs.hh  | 43 +++++++++++++++++++++++++++++++++++++++++++
+ src/hb-private.hh | 51
+ +--------------------------------------------------
+ 2 files changed, 44 insertions(+), 50 deletions(-)
+
+commit 92806ee055c8efb68fcbe9e1750ce2532a1f8ab3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Aug 5 21:41:52 2018 -0700
+
+    Move null data definitions to hb-static.cc
+
+    Also remove "    " null data for Tag.  Just use zeroes.
+
+ src/hb-open-type-private.hh        |  3 +--
+ src/hb-ot-layout-common-private.hh |  5 ++---
+ src/hb-private.hh                  | 12 +++++++-----
+ src/hb-static.cc                   | 10 +++++++++-
+ 4 files changed, 19 insertions(+), 11 deletions(-)
+
+commit 1b4d5a2402302e90867c178b6b2ad07541091a74
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 19:55:09 2018 -0700
+
+    Minor
+
+ src/hb-ot-layout-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 7df7963b46223f47e89a5a38c597c874aaa93141
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 19:54:33 2018 -0700
+
+    Make lazy loader deal with OOM
+
+ src/hb-machinery-private.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 30ff8ac865a266c8dca11eeac155c2cd3d1aa159
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 17:32:00 2018 -0700
+
+    Rename
+
+ src/hb-machinery-private.hh | 6 +++---
+ src/hb-ot-font.cc           | 8 ++++----
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+commit 85ba4a190f30da5147d3b2ddac4d58dda31181f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 17:06:42 2018 -0700
+
+    [ot] Comment
+
+ src/hb-ot-layout-private.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 07afc1a213bde91fdfc44dd613f2e82ac1617c9f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 17:03:32 2018 -0700
+
+    [ot] Add misc tables to tables_t
+
+    Most unused.
+
+ src/hb-ot-layout-private.hh | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+commit 74b4df2cdef68b74536d9c29426b242199a63a6f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 16:57:40 2018 -0700
+
+    [ot] Move GDEF into tables_t
+
+ src/hb-machinery-private.hh          |  6 ++++++
+ src/hb-ot-layout-gsub-table.hh       |  2 +-
+ src/hb-ot-layout-gsubgpos-private.hh |  2 +-
+ src/hb-ot-layout-private.hh          |  7 +------
+ src/hb-ot-layout.cc                  | 15 +++++----------
+ 5 files changed, 14 insertions(+), 18 deletions(-)
+
+commit 0271c7ab3b76dbf8a4e3e92eaf67d9d61b7a63dc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 16:45:57 2018 -0700
+
+    [ot] Move GSUB/GPOS into tables_t
+
+ src/hb-machinery-private.hh    |  6 ++----
+ src/hb-ot-layout-gpos-table.hh |  4 ++--
+ src/hb-ot-layout-gsub-table.hh |  4 ++--
+ src/hb-ot-layout-private.hh    |  7 ++----
+ src/hb-ot-layout.cc            | 49
+ +++++++++++++++++++-----------------------
+ 5 files changed, 30 insertions(+), 40 deletions(-)
+
+commit f73d2775cf649d148ace7c2593da9666d60fc1be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 16:34:25 2018 -0700
+
+    [ot] More shuffling
+
+    Misc. table loading now properly automated.
+
+ src/hb-ot-layout-private.hh | 67
+ +++++++++++++++++++++++++++++----------------
+ src/hb-ot-layout.cc         | 25 +++++++++++------
+ src/hb-ot-math.cc           |  2 +-
+ 3 files changed, 61 insertions(+), 33 deletions(-)
+
+commit 52fbd23d868a989d51b7df5be40be582890d13e5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Aug 3 16:22:16 2018 -0700
+
+    [ot] Minor
+
+ src/hb-aat-layout.cc        |  4 ++--
+ src/hb-face-private.hh      |  7 ++-----
+ src/hb-machinery-private.hh |  1 +
+ src/hb-ot-layout-private.hh | 15 +++++++++------
+ src/hb-ot-layout.cc         | 20 ++++++++++----------
+ src/hb-ot-math.cc           |  2 +-
+ src/hb-ot-var.cc            |  4 ++--
+ 7 files changed, 27 insertions(+), 26 deletions(-)
+
+commit cc3f4e00aa5da1d9f0430adefe30689b3daa8282
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 3 15:00:37 2018 -0700
+
+    silence gcc
+
+ src/hb-ot-cff2-table.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 00970dd2420c3dcc58c25568be4abe6586c159df
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Fri Aug 3 14:35:09 2018 -0700
+
+    Removed parsed hint fields from CFF2PrivateDictValues
+
+    Instead moved & stored uniformly in values vector (renamed from
+    opstrs)
+    This should be fine as we aren't likely going to use them as hints
+    after all
+    Templatized DictValues whether to parse them out
+    For subsetter, they aren't parsed
+
+ src/hb-ot-cff-common-private.hh | 113 ++++++++++++++----------
+ src/hb-ot-cff2-table.hh         | 185
+ ++++++++++++----------------------------
+ src/hb-subset-cff2.cc           |   2 +-
+ 3 files changed, 120 insertions(+), 180 deletions(-)
+
+commit 6a0a298aabe777e2c1ed443f100fe6142c83e3b3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 23:13:19 2018 -0700
+
+    [ot] Move code around
+
+ src/hb-ot-layout.cc | 211
+ ++++++++++++++++++++++++++--------------------------
+ 1 file changed, 106 insertions(+), 105 deletions(-)
+
+commit 5e718a751efdda89511c9f30238b500125193499
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 23:04:42 2018 -0700
+
+    [ot] Use switch for checking for blacklisted GDEF tables
+
+    Faster / more compact code.
+
+ src/hb-ot-layout.cc | 107
+ +++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 59 insertions(+), 48 deletions(-)
+
+commit b5cdf5280d5b00df5356cc5c3236844ca0576bd0
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 22:56:42 2018 -0700
+
+    [ot] In GDEF blacklisting logic, remove the glyph index check
+    for Times
+
+    Just blacklist based on table sizes like we do for other fonts.
+
+ src/hb-ot-layout.cc | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+commit c988b119994ef78d400bc7d3139785312da0be75
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 20:04:37 2018 -0700
+
+    Move code around
+
+ src/hb-ot-font.cc | 41 ++++++++++++++++++++++++++---------------
+ 1 file changed, 26 insertions(+), 15 deletions(-)
+
+commit 76f7397c10832b891a082e30afc74222bd5ffd7b
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 16:28:10 2018 -0700
+
+    templatized CFF2 accelerator for lean Private dict interpretting
+    for subset
+
+    also fixed local subrs serialization
+
+ src/hb-ot-cff-common-private.hh |   8 ++-
+ src/hb-ot-cff2-table.hh         | 119
+ ++++++++++++++++++++++++++++++++--------
+ src/hb-subset-cff2.cc           |  13 +++--
+ 3 files changed, 109 insertions(+), 31 deletions(-)
+
+commit 43040564e661fdd616d39e84fde07612d55bb785
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 12:23:10 2018 -0700
+
+    removed TRACE_SERIALIZE from non-member function _write_cff2
+
+ src/hb-subset-cff2.cc | 29 ++++++++++++++---------------
+ 1 file changed, 14 insertions(+), 15 deletions(-)
+
+commit e2fd49e4779663e3138bd1990736a9cf850303bf
+Merge: 693ae804 d4d1bf81
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 11:39:22 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 693ae804743c60968d4339465fa6480e0ed8396c
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 11:22:42 2018 -0700
+
+    more silencing fixes
+
+ src/hb-ot-cff2-table.hh | 2 +-
+ src/hb-subset-cff2.cc   | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+commit f6da44983178e345ddbac1bcd1691ddb330399c6
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 10:52:08 2018 -0700
+
+    silence archlinux
+
+ src/hb-ot-cff-common-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 58279c3db4f31bf3f9a509d1d88bca01b57c6b81
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Thu Aug 2 10:18:01 2018 -0700
+
+    silence Codacy
+
+ src/hb-ot-cff-common-private.hh | 25 +++++++++++++++++++------
+ src/hb-ot-cff2-table.hh         | 14 +++++++-------
+ 2 files changed, 26 insertions(+), 13 deletions(-)
+
+commit 574b37e933f98e35c2bdae04458a95522bbfbb82
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 02:22:38 2018 -0700
+
+    Minor
+
+ src/hb-ot-font.cc           | 2 +-
+ src/hb-ot-layout-private.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit d4d1bf8177b127caa57b146c932f553dca1ad933
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 02:04:02 2018 -0700
+
+    Fix for recent rename
+
+ src/hb-graphite2.cc | 2 +-
+ src/hb-uniscribe.cc | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+commit 91126aa11a5fa2bff72137df4768ad13fc9b7803
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 02:03:13 2018 -0700
+
+    [uniscribe] Update for recent changes
+
+ src/hb-uniscribe.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 66952ec47b5f09d88b83fb6a71b1cdb26c53668d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 01:44:20 2018 -0700
+
+    Remove unused table reference
+
+ src/hb-ot-layout-private.hh | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit 443de26fa56dd1ef149d3ce4206f4495eceec2eb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 01:41:19 2018 -0700
+
+    Minor
+
+ src/hb-face.cc              |  1 -
+ src/hb-ot-layout-private.hh | 12 ++++++------
+ 2 files changed, 6 insertions(+), 7 deletions(-)
+
+commit ee35af738b5c802ca62eb1c39b77f0bd992329df
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 01:37:57 2018 -0700
+
+    Make lazy-loader safe for nil objectification
+
+ src/hb-machinery-private.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 6404c49d0735d92779089ddef5c1d34aad1542d7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 01:36:08 2018 -0700
+
+    Minor
+
+ src/hb-machinery-private.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit ff7826e90bce46985651015059872d1d8559b6ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 01:27:40 2018 -0700
+
+    Reduce storage by sharing face amongst lazy_loaders
+
+ src/hb-machinery-private.hh | 113
+ ++++++++++++++++++++++++--------------------
+ src/hb-ot-font.cc           |  19 ++++----
+ src/hb-ot-layout-private.hh |  11 +++--
+ src/hb-ot-layout.cc         |   9 ++--
+ 4 files changed, 85 insertions(+), 67 deletions(-)
+
+commit bdd3c11a19d87999eeaff2c82f21c6938d1d9342
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Aug 2 00:38:46 2018 -0700
+
+    Internal templatization of lazy-loaders
+
+ src/hb-machinery-private.hh | 74
+ ++++++++++++++++++++-------------------------
+ 1 file changed, 32 insertions(+), 42 deletions(-)
+
+commit ed7b2e58fc9afb547656cf28eb4a253d989de43c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 23:59:09 2018 -0700
+
+    Remove OT namespace from hb-machinery-private.hh
+
+ src/dump-emoji.cc                          |  4 ++--
+ src/hb-aat-layout.cc                       |  2 +-
+ src/hb-face.cc                             |  4 ++--
+ src/hb-machinery-private.hh                | 14 +++++---------
+ src/hb-ot-font.cc                          |  8 ++++----
+ src/hb-ot-layout-private.hh                | 10 +++++-----
+ src/hb-ot-layout.cc                        |  8 ++++----
+ src/hb-ot-shape-complex-arabic-fallback.hh | 18 +++++++++---------
+ src/hb-static.cc                           |  4 ++--
+ src/hb-subset-glyf.cc                      |  2 +-
+ src/hb-subset.cc                           |  8 ++++----
+ src/hb-uniscribe.cc                        |  2 +-
+ 12 files changed, 40 insertions(+), 44 deletions(-)
+
+commit cb1491f92e24649433988ff81a89347dccf07c8b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 22:50:45 2018 -0700
+
+    Minor
+
+ src/hb-blob-private.hh      |  5 -----
+ src/hb-machinery-private.hh | 10 ++++++----
+ 2 files changed, 6 insertions(+), 9 deletions(-)
+
+commit 16ccfafbbd48c7a9737ce1d12e75406a050b71a9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 22:50:06 2018 -0700
+
+    [face] Sprinkle const in the API
+
+ src/hb-face.cc | 17 +++++++++--------
+ src/hb-face.h  | 16 ++++++++--------
+ 2 files changed, 17 insertions(+), 16 deletions(-)
+
+commit 3d22aefedebb5277c5d79011e48e7be1a26a53c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 18:03:32 2018 -0700
+
+    Rename
+
+ src/hb-coretext.cc       | 46
+ +++++++++++++++++++++++-----------------------
+ src/hb-directwrite.cc    | 28 ++++++++++++++--------------
+ src/hb-fallback-shape.cc | 24 ++++++++++++------------
+ src/hb-graphite2.cc      | 26 +++++++++++++-------------
+ src/hb-ot-shape.cc       | 20 ++++++++++----------
+ src/hb-shaper-private.hh |  2 +-
+ src/hb-uniscribe.cc      | 34 +++++++++++++++++-----------------
+ 7 files changed, 90 insertions(+), 90 deletions(-)
+
+commit 1a624c6e06763a8a61bc686d2d44272d4ef50d4a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 17:53:30 2018 -0700
+
+    Add comment re (our only) race condition
+
+ src/hb-shaper-private.hh | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit 19ce0b24c0173fed11104a8ab039e856cbf40924
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 1 17:34:59 2018 -0700
+
+    removed unused field OpStr::update
+
+ src/hb-ot-cff-common-private.hh |  4 +---
+ src/hb-ot-cff2-table.hh         | 22 +++++++++++-----------
+ 2 files changed, 12 insertions(+), 14 deletions(-)
+
+commit 3bda54c43b248ee2bc18a9210fb4d880bb4d82ac
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 1 16:32:27 2018 -0700
+
+    fixed Index::serialize
+
+    The bug was causing CharString of the last glyph corrupt
+
+ src/hb-ot-cff-common-private.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 16f4dc9b73a197a5ab0ad29dcf5a7ed7495ec4e1
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 1 16:06:52 2018 -0700
+
+    fixed CFF2VariationStore::serialize
+
+    also get_size
+
+ src/hb-ot-cff2-table.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 44d1fb37efa20852cc466c0f0bba95dbd24ce288
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 14:51:51 2018 -0700
+
+    1.8.5
+
+ NEWS                | 8 ++++++++
+ configure.ac        | 2 +-
+ src/hb-ot-layout.cc | 2 +-
+ src/hb-version.h    | 4 ++--
+ 4 files changed, 12 insertions(+), 4 deletions(-)
+
+commit 13f4c137c686aed5c2888b5c47d9f16892be0d5e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 14:13:59 2018 -0700
+
+    [atomic] Fix Solaris ones to add proper barriers
+
+ src/hb-atomic-private.hh | 52
+ +++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 36 insertions(+), 16 deletions(-)
+
+commit 19dfaa351568887a74cee2c46d6acfcc3fa718ff
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 14:02:39 2018 -0700
+
+    [atomic] Remove volatile from IBM impl signature
+
+ src/hb-atomic-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 2093a3e0cbb98c2daa39f308d50a12f0a719bc81
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 14:00:46 2018 -0700
+
+    [atomic] Oops
+
+ src/hb-atomic-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 19b98348ffc660501e518bf48cd63d232f7585e7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 13:59:59 2018 -0700
+
+    [atomic] Use read-barrier for get()
+
+ src/hb-atomic-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 006d4f031a30dd04f5bb9c3d1daca187ef6b7f1e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 13:59:31 2018 -0700
+
+    [atomic] Some more minor tweaks
+
+ src/hb-atomic-private.hh | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+commit 28d03a8afcc1f0ba6d9d0d88f669cc53bb030dd8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Aug 2 00:11:43 2018 +0430
+
+    [ci] Fix Appveyor bot (#1123)
+
+ appveyor.yml | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit b2ff582c8c1a0fea60ee323dc820ce6fe807b063
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Aug 1 11:30:38 2018 -0700
+
+    Implemented hb_subset_cff2
+
+    Added serialize functions to CFF2 structs
+    Fixed issues & bugs & code cleanup
+    Now subsetting CFF2 table outputs something
+
+ src/hb-ot-cff-common-private.hh | 428
+ +++++++++++++++++++++++++++++++++++-----
+ src/hb-ot-cff2-table.hh         | 237 +++++++++++++++++-----
+ src/hb-private.hh               |   2 +-
+ src/hb-subset-cff2.cc           | 392
+ +++++++++++++++++++++++++++++++-----
+ 4 files changed, 914 insertions(+), 145 deletions(-)
+
+commit 1a7fed631880fff8a947ebec9c7427efff581916
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Aug 1 12:15:44 2018 +0430
+
+    Revert "Add a new API, hb_ot_layout_get_feature_name_ids (#976)"
+    (#1121)
+
+    This reverts commit 0c1b287b72e91e0898d75acb5d5acf1c6b9a7498.
+
+ docs/harfbuzz-sections.txt         |  1 -
+ src/hb-ot-layout-common-private.hh | 14 -------
+ src/hb-ot-layout.cc                | 86
+ --------------------------------------
+ src/hb-ot-layout.h                 |  8 ----
+ 4 files changed, 109 deletions(-)
+
+commit dfc86e4b35ffdeb8f73e83511712e75413bbb7d9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 00:22:18 2018 -0700
+
+    [atomic] Fix cast to fallback ptr_get()
+
+ src/hb-atomic-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7a4d576e81c4de68ea66b2d5fe7712e29d715272
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Aug 1 00:19:25 2018 -0700
+
+    [gobject] Fix copy/paste error
+
+ src/hb-gobject-structs.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ad275627425c9b3c4fb1e69aa408067bd0bb77da
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 23:01:05 2018 -0700
+
+    [atomic] On IBM, use light-weight sync for everything
+
+    lwsync() is a full read/write-barrier.  That's all we need, never
+    need sync().  I'm not sure why an isync() was used in fetch_and_add,
+    but since that's a read-modify-write, I just changed it to have
+    lwsync() on both sides.
+
+ src/hb-atomic-private.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit fd638d215feb058c2294e447cc68f6f50e2b481d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 23:00:15 2018 -0700
+
+    [atomic] Add XXX items around Solaris ops
+
+    Since add_int and cas are both read-modify-write, I wonder if we
+    also need a barrier after them.
+
+ src/hb-atomic-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 896ff15ae60a4a4b94c62946e69196b877839bb5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 22:51:38 2018 -0700
+
+    [atomic] Fix get() impl
+
+    Originally, glib's atomic_get was implemented as "memory_barrier;
+    load".
+    I copied this into cairo, fontconfig, and harfbuzz.  However, that's
+    wrong.  Correct way is "load; memory_barrier".  The details are long
+    and hard to fully grasp.  Best to read:
+
+      https://www.kernel.org/doc/Documentation/memory-barriers.txt
+
+    Also see my report against GNOME:
+
+      https://gitlab.gnome.org/GNOME/glib/issues/1449
+
+    Note that this is irrelevant if C++11-like atomic ops are available.
+
+ src/hb-atomic-private.hh | 28 +++++++++++++++++-----------
+ 1 file changed, 17 insertions(+), 11 deletions(-)
+
+commit d7a15799d40dac1f9521674a82c3293a7cb42ee4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 22:28:28 2018 -0700
+
+    [gobject] Hook up hb_map_t
+
+ docs/harfbuzz-sections.txt | 2 ++
+ src/hb-gobject-structs.cc  | 1 +
+ src/hb-gobject-structs.h   | 4 ++++
+ src/hb-map.cc              | 6 ++----
+ 4 files changed, 9 insertions(+), 4 deletions(-)
+
+commit 63c74e8d1d85067cbeffe635eb5ed4e8aa130776
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 22:21:21 2018 -0700
+
+    [atomic] Fix fallback impl
+
+ src/hb-atomic-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4bc16aca4760ac9ffd8c63bbaea24fc7d234f715
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 21:05:51 2018 -0700
+
+    [atomic] Add get_relaxed / set_relaxed
+
+    To help TSan and be more "correct".
+
+ src/hb-atomic-private.hh         | 37 ++++++++++++++++++++++-------------
+ src/hb-common.cc                 |  4 ++--
+ src/hb-debug.hh                  | 42
+ ++++++++++++++++++++++++++++++++++++++++
+ src/hb-object-private.hh         | 12 ++++++------
+ src/hb-ot-shape-complex-indic.cc | 22 +++++++++++----------
+ src/hb-private.hh                | 28 ---------------------------
+ 6 files changed, 86 insertions(+), 59 deletions(-)
+
+commit 3dd1b88765f6ce91bd0558a16cdd8cf0c1e15d1b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 19:33:37 2018 -0700
+
+    [atomic] Use CONSUME, not ACQUIRE, memory-order for get()
+
+    Although, all implementations just elevate that to ACQUIRE.
+    But requirement for us is just CONSUME.
+
+ src/hb-atomic-private.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 06b91d935da1a40ef9de6697717eb0af1015989e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 19:29:49 2018 -0700
+
+    Revert "[atomic] Make pointer get op relaxed instead of acquire"
+
+    This reverts commit b1e5650c67266dc158f22355fed206cd1c413f70.
+
+    After lots of head-scratching and finally finding the only truly
+    readable source to be the good old:
+
+      https://www.kernel.org/doc/Documentation/memory-barriers.txt
+
+    I've convinced myself that we need consume memory-ordering on get().
+    The location of memory-barrier in a load should be after, not before
+    the load.  That needs fixing.  I'll do that separately.
+
+ src/hb-atomic-private.hh | 34 +++++++++++++++++++++++++---------
+ 1 file changed, 25 insertions(+), 9 deletions(-)
+
+commit 2bdd903c69eb3a34f3d3bf5e4f4c94cd66337117
+Author: Garret Rieger <grieger@google.com>
+Date:   Tue Jul 31 17:44:02 2018 -0700
+
+    [subset] limit the max codepoint value to the unicode limit.
+    When collecting all codepoints in the cmap avoid using large amount
+    of memory for fonts that declare coverage over all 32 bit integers.
+
+ src/hb-ot-cmap-table.hh                                   |   9 +++++++--
+ ...mized-hb-subset-get-codepoints-fuzzer-5973295416475648 | Bin 0 ->
+ 109 bytes
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+commit 7278d9df3093a87f99cec9b4cea38bd688c5d020
+Author: Garret Rieger <grieger@google.com>
+Date:   Tue Jul 31 17:59:19 2018 -0700
+
+    [subset] Add hb_ot_layout_collect_features to harfbuzz-sections.txt.
+    Add the fuzzer test case for feature collection timeout.
+
+ docs/harfbuzz-sections.txt                             |   1 +
+ ...estcase-minimized-hb-subset-fuzzer-5542653037903872 | Bin 0 ->
+ 160249 bytes
+ 2 files changed, 1 insertion(+)
+
+commit 89733755a48feef0a663e1ea7b8294949581ce7e
+Author: Garret Rieger <grieger@google.com>
+Date:   Mon Jul 30 18:10:43 2018 -0700
+
+    [subset] use add_array to populate feature_indexes.
+    This is much faster then calling a bunch of individual add()'s.
+
+ src/hb-ot-layout-common-private.hh |  7 +++++++
+ src/hb-ot-layout.cc                | 40
+ +++++++++++++++++++-------------------
+ 2 files changed, 27 insertions(+), 20 deletions(-)
+
+commit 7d92bef9c5afb319d125f60b0fce4763afeaa686
+Author: Garret Rieger <grieger@google.com>
+Date:   Mon Jul 30 17:17:43 2018 -0700
+
+    [subset] collect features first, then use those to collect lookups.
+
+ src/hb-ot-layout.cc | 148
+ +++++++++++++++++++++++++---------------------------
+ src/hb-ot-layout.h  |   7 +++
+ 2 files changed, 78 insertions(+), 77 deletions(-)
+
+commit af876cce3066833c7c34d213a578eec6b09dd5c9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 15:27:29 2018 -0700
+
+    [indic] Flip default logic for double-halants in old-school
+
+    Oriya went down from 9 to 2.
+
+    BENGALI: 353725 out of 354188 tests passed. 463 failed (0.130722%)
+    DEVANAGARI: 707311 out of 707394 tests passed. 83 failed (0.0117332%)
+    GUJARATI: 366355 out of 366457 tests passed. 102 failed (0.0278341%)
+    GURMUKHI: 60729 out of 60747 tests passed. 18 failed (0.0296311%)
+    KANNADA: 951300 out of 951913 tests passed. 613 failed (0.0643966%)
+    MALAYALAM: 1048136 out of 1048334 tests passed. 198 failed
+    (0.0188871%)
+    MYANMAR: 1115830 out of 1123883 tests passed. 8053 failed (0.716534%)
+    ORIYA: 42327 out of 42329 tests passed. 2 failed (0.00472489%)
+    SINHALA: 271596 out of 271847 tests passed. 251 failed (0.0923313%)
+    TAMIL: 1091754 out of 1091754 tests passed. 0 failed (0%)
+    TELUGU: 970555 out of 970573 tests passed. 18 failed (0.00185457%)
+
+ src/hb-ot-shape-complex-indic.cc | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 92ba9905caa060466230f63b428ccee767696464
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 15:19:32 2018 -0700
+
+    [indic] Allow double-halant in old-spec Devanagari
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1071
+
+ src/hb-ot-shape-complex-indic.cc                      |  18
+ ++++++++++++------
+ .../b722a7d09e60421f3efbc706ad348ab47b88567b.ttf      | Bin 0 ->
+ 4672 bytes
+ test/shaping/data/in-house/tests/indic-old-spec.tests |   2 ++
+ 3 files changed, 14 insertions(+), 6 deletions(-)
+
+commit fe099a844b9b8fe05dd4eb187b5ca3769441f012
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 14:20:31 2018 -0700
+
+    [test] Add Khmer tests, with NotoSansKhmer-Regular.ttf
+
+    Note that there's minor positioning differences, and ONE reordering
+    difference between what we get for these and what Uniscribe gets.
+    Probably same as what's described in commit message for
+    1a96cc825dc9c8e3b6eef1403fe0864a1cfc0245
+
+ .../3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf   | Bin 0 -> 24392 bytes
+ test/shaping/data/in-house/tests/khmer-misc.tests  |  89
+ +++++++++++++++++++++
+ 2 files changed, 89 insertions(+)
+
+commit 5772edc0ea8f697c6123e439c5d0c3e813ebeb45
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 14:10:31 2018 -0700
+
+    [khmer] Typo
+
+ src/hb-ot-shape-complex-khmer.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2d6edc9008182c1446951f2c5c04df20094597f8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 13:56:55 2018 -0700
+
+    [test] Add Khmer test texts from recent bugs
+
+ test/shaping/texts/in-house/shaper-khmer/misc.txt | 66
+ +++++++++++++++++++++++
+ 1 file changed, 66 insertions(+)
+
+commit df26a32c8fd22cbd486e2a1014d30b9f38f51cd1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 13:55:53 2018 -0700
+
+    [test] Move things around for shaper updates
+
+ .../texts/in-house/shaper-indic/{indic => }/script-assamese/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-assamese/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-assamese/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-assamese/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-assamese/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-assamese/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-assamese/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-bengali/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-bengali/misc/reph.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-bengali/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-bengali/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-bengali/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../script-bengali/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-bengali/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-bengali/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-bengali/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../shaper-indic/{indic => }/script-devanagari/misc/dottedcircle.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/misc/eyelash.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/misc/joiners.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/misc/misc.txt
+ | 0
+ .../shaper-indic/{indic => }/script-devanagari/misc/spec-deviations.txt
+ | 0
+ .../shaper-indic/{indic => }/script-devanagari/misc/tricky-reordering.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/utrrs/LICENSE
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/utrrs/README
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-devanagari/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../codepoint/IndicFontFeatureCodepoint-DevnagariSpecificAddition.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-GenericPunctuation.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-devanagari/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-devanagari/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gujarati/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gujarati/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gujarati/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-gujarati/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-gujarati/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-gujarati/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gurmukhi/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gurmukhi/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gurmukhi/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-gurmukhi/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-gurmukhi/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-GurmukhiSpecific.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-gurmukhi/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-gurmukhi/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-kannada/misc/misc.txt
+ | 0
+ .../shaper-indic/{indic => }/script-kannada/misc/right-matras.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-kannada/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-kannada/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-kannada/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../script-kannada/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-kannada/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../{indic => }/script-kannada/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-malayalam/misc/cibu.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-malayalam/misc/dot-reph.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-malayalam/misc/misc.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-malayalam/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-malayalam/utrrs/README
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-malayalam/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-malayalam/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../{indic => }/script-malayalam/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-oriya/misc/bindu.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-oriya/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-oriya/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-oriya/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-oriya/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalConsonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-OriyaSpecific.txt
+ | 0
+ .../script-oriya/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../{indic => }/script-oriya/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../in-house/shaper-indic/{indic => }/script-sinhala/misc/extensive.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-sinhala/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-sinhala/misc/reph.txt
+ | 0
+ .../shaper-indic/{indic => }/script-sinhala/misc/split-matras.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-sinhala/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-sinhala/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-sinhala/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Punctuation.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../{indic => }/script-sinhala/utrrs/gpos/IndicFontFeatureGPOS.txt
+ | 0
+ .../script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Conjunct.txt
+ | 0
+ .../script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Rakaaraansaya.txt
+ | 0
+ .../{indic => }/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Repaya.txt
+ | 0
+ .../script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Special-Cases.txt
+ | 0
+ .../script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-TouchingLetters.txt
+ | 0
+ .../script-sinhala/utrrs/gsub/IndicFontFeatureGSUB-Yansaya.txt
+ | 0
+ .../{indic => }/script-sinhala/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-tamil/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-tamil/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-tamil/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-tamil/utrrs/SOURCES
+ | 0
+ .../script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-CurrencySymbols.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Numerics.txt
+ | 0
+ .../script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../script-tamil/utrrs/codepoint/IndicFontFeatureCodepoint-Symbols.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-TamilSymbol.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-tamil/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../script-tamil/utrrs/gpos/IndicFontFeatureGPOS-BelowBase.txt
+ | 0
+ .../{indic => }/script-tamil/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-telugu/misc/misc.txt
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-telugu/utrrs/LICENSE
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-telugu/utrrs/README
+ | 0
+ .../texts/in-house/shaper-indic/{indic => }/script-telugu/utrrs/SOURCES
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-AdditionalVowels.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-Consonants.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-DependentVowels.txt
+ | 0
+ .../script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Digits.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-IndependentVowels.txt
+ | 0
+ .../script-telugu/utrrs/codepoint/IndicFontFeatureCodepoint-Reserved.txt
+ | 0
+ .../utrrs/codepoint/IndicFontFeatureCodepoint-VariousSigns.txt
+ | 0
+ .../script-telugu/utrrs/gpos/IndicFontFeatureGPOS-AboveBase.txt
+ | 0
+ .../{indic => }/script-telugu/utrrs/gsub/IndicFontFeatureGSUB.txt
+ | 0
+ .../south-east-asian/script-khmer/misc => shaper-khmer}/misc.txt
+ | 0
+ .../script-khmer/misc => shaper-khmer}/other-marks-invalid.txt
+ | 0
+ .../south-east-asian/script-khmer/misc => shaper-khmer}/other-marks.txt
+ | 0
+ .../south-east-asian => shaper-use}/script-javanese/misc.txt
+ | 0
+ 174 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 6ddd669e205cf2c1c3b0a362330b686386f68519
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 13:38:07 2018 -0700
+
+    [khmer] Clear syllables before presentation features
+
+    Probably not what Uniscribe does, but good idea?
+
+ src/hb-ot-shape-complex-khmer.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 8eef1964a708c3db52e5e7312689c4664afa9839
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 13:35:10 2018 -0700
+
+    [khmer] Revert previous change, and remove pauses
+
+    This makes test suite happy again (at 44) while fixing the sequences
+    we were fixing, which were the following with KhmerUI.ttf:
+
+      U+1789,U+17BC
+      U+1789,U+17D2,U+1789
+      U+1789,U+17D2,U+1789,U+17BC
+
+    Fixes rest of https://github.com/harfbuzz/harfbuzz/issues/974
+
+ src/hb-ot-shape-complex-khmer.cc | 23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+commit 7c658ea2f20a77cac35e8988e54316425396198a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 12:49:02 2018 -0700
+
+    [khmer] Apply ccmp after basic features
+
+    Part of https://github.com/harfbuzz/harfbuzz/issues/974
+
+ src/hb-ot-shape-complex-khmer.cc | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+commit 1a96cc825dc9c8e3b6eef1403fe0864a1cfc0245
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 11:45:32 2018 -0700
+
+    [khmer] Rewrite most of shaper to better follow spec
+
+    Khmer spec has only one reordering phase, and only simple prebase
+    matra and Coeng-Ro reordering.  Implement that.  Specifically,
+    this was done to address recognizing different orders of the matra
+    and Coeng-Ro sequence.  That said, some combinations are now
+    reordered differently from Uniscribe.  Not clear if that's intended
+    or a bug in Uniscribe.  The following two sequences render the same
+    in Uniscribe whereas we reorder them differently:
+
+      U+17A0,U+17D2,U+179A,U+17C2
+      U+17A0,U+17C2,U+17D2,U+179A
+
+    For that reason, our test suite numbers regressed slightly.  Used
+    to be at 34 for fails, now at:
+
+    KHMER: 299080 out of 299124 tests passed. 44 failed (0.0147096%)
+
+    But generally a good change, and removed lots of code.
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1026
+
+ src/hb-ot-shape-complex-indic-private.hh |   4 +-
+ src/hb-ot-shape-complex-khmer.cc         | 460
+ ++++---------------------------
+ src/hb-ot-shape-complex-private.hh       |  13 -
+ 3 files changed, 64 insertions(+), 413 deletions(-)
+
+commit f5152cea423947cd8a85332566443b4e2e091672
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 01:27:04 2018 -0700
+
+    [shaper] Move code around
+
+ src/hb-shaper-private.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 36d0fbbc52bdf2c71da022fb1fdc31eca17078ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 01:15:04 2018 -0700
+
+    [shaper] Remove a macro
+
+ src/hb-shaper-private.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit b1e5650c67266dc158f22355fed206cd1c413f70
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 31 01:02:31 2018 -0700
+
+    [atomic] Make pointer get op relaxed instead of acquire
+
+    We only use it before cmpexch, so relaxed is fine and faster for
+    common case.
+
+ src/hb-atomic-private.hh | 34 +++++++++-------------------------
+ 1 file changed, 9 insertions(+), 25 deletions(-)
+
+commit 66ccd8ac405c9c25b37de9eb467a7382880dda35
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 30 17:03:06 2018 -0700
+
+    [serialize] Increase stage count from 8 to 32
+
+    Indic shaper uses many stages.  Now we are provably not limiting
+    functionality whereas the previous limit of 8 was assuming real-world
+    practices.
+
+ src/hb-ot-layout-common-private.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit ee8cf919654cb191e955fe1f89b1ebfb2b8b32ee
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 30 16:59:41 2018 -0700
+
+    [serialize] Remove unused truncate() method
+
+ src/hb-machinery-private.hh | 6 ------
+ 1 file changed, 6 deletions(-)
+
+commit 8782f80cce147c101b605501d9fd9c7d64338314
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Jul 30 15:27:20 2018 -0700
+
+    fixed FDSelect0::sanitize
+
+ src/hb-ot-cff-common-private.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 9c4cadaef01733b32ab6190dd91552ee7145f3c3
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Jul 30 14:28:40 2018 -0700
+
+    Added sanitize functions & calls
+
+    Added sanitize functions to FDSelect
+    Added satnitize calls for FDSelect, VariationStore, FDArray, TopDict
+
+ src/hb-ot-cff-common-private.hh | 67
+ ++++++++++++++++++++++++++++++++---------
+ src/hb-ot-cff2-table.hh         | 26 +++++++++++-----
+ src/hb-subset-cff2.cc           |  2 +-
+ 3 files changed, 72 insertions(+), 23 deletions(-)
+
+commit 161b642ec5babc7e4b81d41f725d81ad2caa9330
+Merge: 3a61c3e9 5edf454a
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Mon Jul 30 12:22:09 2018 -0700
+
+    Merge branch 'master' into cff-subset
+
+commit 5edf454aa64aad461c90bd991e7eaf27668b7e6b
+Author: Garret Rieger <grieger@google.com>
+Date:   Thu Jul 26 17:42:02 2018 -0700
+
+    [subset] During lookup collection remember the features we've
+    already processed.
+
+ src/hb-ot-layout.cc                                |  26
+ +++++++++++++++++----
+ ...ase-minimized-hb-subset-fuzzer-5670861909524480 | Bin 0 -> 1298 bytes
+ ...b-subset-get-codepoints-fuzzer-6136125075750912 | Bin 0 -> 65816 bytes
+ 3 files changed, 21 insertions(+), 5 deletions(-)
+
+commit 42c183f80355fe7cadac2931a23d389285c8b98c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Fri Jul 27 14:55:29 2018 -0700
+
+    Minor
+
+ src/hb-ft.cc       | 5 +++--
+ src/hb-ot-shape.cc | 5 +++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+commit ecab6604e57ea2bb4e78250a7a400e15b3e86f7a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 17:37:38 2018 -0700
+
+    [serialize] Allocate for markFilteringSet
+
+ src/hb-ot-layout-common-private.hh | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 7f08818c441517f73c5bea0a2a88f494dfc8fa58
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 17:22:05 2018 -0700
+
+    Minor
+
+ src/hb-iter-private.hh      | 8 +++++---
+ src/hb-machinery-private.hh | 1 -
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+commit 2e25d8f49181ab1d7fda520ae6587d293a982acf
+Author: prrace <philip.race@oracle.com>
+Date:   Fri Jul 27 13:58:27 2018 -0700
+
+    Fix unlikely leaks
+
+ src/hb-ft.cc       | 4 +++-
+ src/hb-ot-shape.cc | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+commit 3c2842cbcf8cded73d1e310379e1a4ca124a6fc2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 17:07:17 2018 -0700
+
+    Add hb-iter-private.hh
+
+    Unused so far.
+
+ src/Makefile.sources        |   1 +
+ src/hb-iter-private.hh      | 147
+ ++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-machinery-private.hh |   1 +
+ 3 files changed, 149 insertions(+)
+
+commit 92b1e025c639d006f55400bf68fc23bdeaa1c716
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 16:58:47 2018 -0700
+
+    Move some code from hb-open-type-private.hh to hb-machinery-private.hh
+
+ src/Makefile.sources        |   1 +
+ src/hb-machinery-private.hh | 702
+ ++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-open-type-private.hh | 669
+ +----------------------------------------
+ 3 files changed, 706 insertions(+), 666 deletions(-)
+
+commit 6b11fea99716e22522b563d919ef7c72fe9a3c45
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 16:01:37 2018 -0700
+
+    [closure] Allocate out set on the stack
+
+ src/hb-ot-layout-gsubgpos-private.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 74467b790154838e86c3ca8df0eaafe82e87f976
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 25 14:30:07 2018 -0700
+
+    Fix compile
+
+ src/hb-shaper-private.hh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit bf90f35302c319ec4699ccbcd1e28b15ef2ec423
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 24 18:00:14 2018 -0700
+
+    [coretext] Add note
+
+ src/hb-shaper-private.hh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit fb58cb4b5ca7043fa746b1a01790abf53bedfa86
+Author: Garret Rieger <grieger@google.com>
+Date:   Wed Jul 25 13:39:17 2018 -0700
+
+    [subset] Only used reachable lookups for gsub closure.
+
+ src/hb-subset-plan.cc | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+commit c38bd4025f3f6ff4c1a39cc106b8618361a0c62b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 24 09:43:27 2018 -0700
+
+    [closure] Separate in and out glyphs
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1107
+
+ src/hb-ot-layout-gsub-table.hh       | 26 ++++++++++++++++++--------
+ src/hb-ot-layout-gsubgpos-private.hh | 16 +++++++++++++++-
+ 2 files changed, 33 insertions(+), 9 deletions(-)
+
+commit 85646fdadb2f102333485e07425361795b4e0412
+Author: Garret Rieger <grieger@google.com>
+Date:   Mon Jul 23 15:37:18 2018 -0700
+
+    [subset] Limit the iterations of the closure algorithm.
+    Prevents O(n^2) run times.
+
+ src/hb-ot-layout-common-private.hh | 7 +++++++
+ src/hb-ot-layout.cc                | 5 ++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+commit 94759d4cf8986388399026ef5204ac55ee187180
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 15:01:39 2018 -0700
+
+    Fix visibility on mingw32
+
+    Should fix bots again.
+
+ src/hb-private.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 61eddbd8ef64dc66e3c42723533d53967e61c9af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 14:44:10 2018 -0700
+
+    Fix infinite loop in loading num_glyphs within sanitizer
+
+ src/hb-open-type-private.hh | 13 ++++++++++---
+ src/hb-static.cc            |  4 +++-
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+commit e22a48ac95a60fac5e1bca26eed7f5623d73a7be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 13:24:26 2018 -0700
+
+    One more visibility trick
+
+    Should fix Windows build again.
+
+ src/hb-common.cc  |  9 +++++++++
+ src/hb-private.hh | 20 ++------------------
+ src/hb-static.cc  |  4 +++-
+ 3 files changed, 14 insertions(+), 19 deletions(-)
+
+commit e57a638bdec378eed8e83513818c8add3ffae896
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 12:00:02 2018 -0700
+
+    One more
+
+ src/hb-ot-cmap-table.hh | 40 ++++++++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 20 deletions(-)
+
+commit 36ed163fdd50419e4619c665a4a9dbf97f66c349
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 11:57:45 2018 -0700
+
+    Remove unnecessary OT:: namespace specifiers
+
+ src/hb-ot-cmap-table.hh       | 30 +++++++++++++++---------------
+ src/hb-ot-color-sbix-table.hh |  4 ++--
+ src/hb-ot-color-svg-table.hh  |  4 ++--
+ src/hb-ot-glyf-table.hh       |  4 ++--
+ src/hb-ot-hmtx-table.hh       |  2 +-
+ src/hb-ot-maxp-table.hh       |  6 +++---
+ src/hb-ot-os2-table.hh        |  4 ++--
+ src/hb-ot-post-table.hh       |  2 +-
+ 8 files changed, 28 insertions(+), 28 deletions(-)
+
+commit c6bc7c38314ea831418fdd1434bbe5afc0875f33
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 23 11:46:46 2018 -0700
+
+    Set num glyphs on sanitizer reference_table()
+
+    Move out-of-class definitions of two methods to hb-static so they
+    are accessible in libharfbuzz-subset.
+
+ src/hb-face.cc              | 20 --------------------
+ src/hb-open-type-private.hh |  1 +
+ src/hb-static.cc            | 22 ++++++++++++++++++++++
+ 3 files changed, 23 insertions(+), 20 deletions(-)
+
+commit 9401829d4e93f6f433957fa2d053f3b9d42da557
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:50:58 2018 -0700
+
+    Remove Sanitizer<>
+
+ src/hb-open-type-private.hh | 16 +---------------
+ 1 file changed, 1 insertion(+), 15 deletions(-)
+
+commit 8e3e41272b3896274459c5961aac813ef2666321
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:49:26 2018 -0700
+
+    Port rest of code away from Sanitizer<>
+
+ src/hb-face.cc | 4 ++--
+ src/main.cc    | 3 +--
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+commit d6a8f64045ca3bf4c7d01520909fa0c7dfca4d64
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:47:19 2018 -0700
+
+    Port dump-emoji away from Sanitizer<>
+
+ src/dump-emoji.cc | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 14f78d2b3bb1e1292efbd6a3e3f0d618179c171a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:45:26 2018 -0700
+
+    .
+
+ src/hb-aat-layout.cc | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 4547051f48ca6aa53309b81a768b5b44c4ab6e3b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:44:22 2018 -0700
+
+    Minor
+
+ src/hb-open-file-private.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 740ae27d5c0f5ff87e2ff489fb49d5db1a0c95be
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:40:56 2018 -0700
+
+    Port sbix off of Sanitizer<>
+
+ src/hb-ot-color-sbix-table.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 9583e0077d0a3a043f8b5bd23925014e04da8d32
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:40:32 2018 -0700
+
+    Port more off of Sanitizer<>
+
+ src/hb-face.cc                |  4 ++--
+ src/hb-open-type-private.hh   |  2 +-
+ src/hb-ot-cmap-table.hh       |  2 +-
+ src/hb-ot-color-cbdt-table.hh |  4 ++--
+ src/hb-ot-color-svg-table.hh  |  4 +---
+ src/hb-ot-glyf-table.hh       |  8 ++++----
+ src/hb-ot-hmtx-table.hh       | 10 +++++-----
+ src/hb-ot-kern-table.hh       |  2 +-
+ src/hb-ot-layout.cc           |  6 +++---
+ src/hb-ot-maxp-table.hh       |  2 +-
+ src/hb-ot-os2-table.hh        |  2 +-
+ src/hb-ot-post-table.hh       |  2 +-
+ src/hb-subset.cc              |  4 +---
+ 13 files changed, 24 insertions(+), 28 deletions(-)
+
+commit e7737b41d793bfce9455d1797eb5e0af60794f23
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sun Jul 22 22:24:31 2018 -0700
+
+    Add sanitizer reference_table, also fix clang build
+
+    Clang is being really peculiar.  Fix with:
+
+    -  inline hb_blob_t *sanitize (hb_blob_t *blob) { return
+    c->sanitize<Type> (blob); }
+    +  inline hb_blob_t *sanitize (hb_blob_t *blob) { return
+    c[0].template/*clang idiosyncrasy*/sanitize_blob<Type> (blob); }
+
+ src/hb-open-type-private.hh | 10 ++++++++--
+ src/hb-ot-post-table.hh     |  2 +-
+ src/hb-subset-glyf.cc       |  2 +-
+ src/hb-uniscribe.cc         |  2 +-
+ 4 files changed, 11 insertions(+), 5 deletions(-)
+
+commit 62fa7cd1ccff4d4448ef84f9cc146464672636aa
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Apr 13 18:45:37 2018 -0400
+
+    Order Chakma split vowels in accordance with NFC
+
+    Fixes #1105.
+
+ src/gen-use-table.py                               |  10 ++++++++++
+ src/hb-ot-shape-complex-use-table.cc               |   4 ++--
+ src/hb-ot-shape-complex-use.cc                     |  21
+ +--------------------
+ .../2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf   | Bin 0 -> 1344 bytes
+ test/shaping/data/in-house/tests/use.tests         |   5 +++++
+ 5 files changed, 18 insertions(+), 22 deletions(-)
+
+commit 0c1b287b72e91e0898d75acb5d5acf1c6b9a7498
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sat Jul 21 21:14:48 2018 +0430
+
+    Add a new API, hb_ot_layout_get_feature_name_ids (#976)
+
+    This new API returns cvXX and ssXX related NameId, things like
+    featUiLabelNameId, featUiTooltipTextNameId, sampleTextNameId,
+    ... of cvXX
+    and UINameId of ssXX, in a unified way.
+
+    However HarfBuzz currently doesn't expose an API for retrieving
+    the actual
+    information associated with NameId from the `name` table and that
+    should be
+    done separately.
+
+ docs/harfbuzz-sections.txt         |  1 +
+ src/hb-ot-layout-common-private.hh | 14 +++++++
+ src/hb-ot-layout.cc                | 86
+ ++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-layout.h                 |  8 ++++
+ 4 files changed, 109 insertions(+)
+
+commit 3a61c3e935cf649ba65ef0cb4daa9f06ab5d3c0a
+Author: Michiharu Ariza <ariza@adobe.com>
+Date:   Wed Jul 18 14:17:52 2018 -0700
+
+    first push of CFF/CFF2 work
+
+    Index, Dict structs
+    hooked up to hb-subset (takes CFF2, outputs empty CFF2)
+
+ src/Makefile.sources            |   4 +
+ src/hb-ot-cff-common-private.hh | 475
+ ++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-cff2-table.hh         | 386 ++++++++++++++++++++++++++++++++
+ src/hb-ot-font.cc               |   2 +
+ src/hb-subset-cff2.cc           | 121 ++++++++++
+ src/hb-subset-cff2.hh           |  38 ++++
+ src/hb-subset.cc                |   4 +
+ 7 files changed, 1030 insertions(+)
+
+commit 93b65d9fe331a217640069fad4159cb7c3ec35e6
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Jul 17 23:29:16 2018 +0430
+
+    Remove dump-fon (#1100)
+
+    It had interesting stuffs like EXE parsing and
+    big-endian parsers but added in an attempt to find
+    a solution for #681 which later found not related.
+
+ src/Makefile.am |   4 -
+ src/dump-fon.cc | 555
+ --------------------------------------------------------
+ 2 files changed, 559 deletions(-)
+
+commit d5cd47a69c40966b4d5b5aed87dd7ac6f070c37a
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Jul 17 22:32:37 2018 +0430
+
+    Remove AAT's gcid/fmtx (#1099)
+
+    We are not going to use them, at least in the foreseeable future
+
+ src/Makefile.sources     |  2 --
+ src/hb-aat-fmtx-table.hh | 67
+ --------------------------------------------
+ src/hb-aat-gcid-table.hh | 73
+ ------------------------------------------------
+ src/hb-aat-layout.cc     |  2 --
+ 4 files changed, 144 deletions(-)
+
+commit 1e9e344b2ba076a5fd6d57d1705e17a59c3875ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 19:17:59 2018 +0200
+
+    Fix hb_face_count() sanitize referencing
+
+ src/hb-face.cc | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit a8cc0b5907e61199334a3a886fe22efe9cc17149
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 19:09:03 2018 +0200
+
+    Remove TODO that is not gonna be done
+
+    Previously the idea was to cache sanitize results externally (think,
+    in Fontconfig) and avoid resanitizing every time.  That's, not a good
+    idea.
+
+ src/hb-open-type-private.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit be7073840097c873ce4954c6cffadab175a007d3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 18:45:25 2018 +0200
+
+    Move sanitizer code around a bit
+
+ src/hb-aat-layout-common-private.hh |  4 +-
+ src/hb-open-type-private.hh         | 95
+ ++++++++++++++++++++-----------------
+ src/hb-ot-color-sbix-table.hh       | 12 ++---
+ src/hb-ot-layout-common-private.hh  |  3 --
+ 4 files changed, 58 insertions(+), 56 deletions(-)
+
+commit db5d430effce67db57ddea2545694b7275ee8b35
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 18:14:45 2018 +0200
+
+    [aat] Update for blob changes
+
+    Also, uncomment code again, just "if (0)" it out, so it doesn't get
+    stale again.
+
+ src/hb-aat-layout.cc        | 58
+ ++-------------------------------------------
+ src/hb-open-type-private.hh | 27 +++++++++++++--------
+ src/hb-ot-layout-private.hh |  1 +
+ src/hb-ot-layout.cc         |  2 ++
+ src/hb-ot-shape.cc          |  6 ++---
+ 5 files changed, 25 insertions(+), 69 deletions(-)
+
+commit 68310a65cba7eed20f8696f4c670bb195677f467
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 13:20:40 2018 +0200
+
+    1.8.4
+
+ NEWS             | 7 +++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 10 insertions(+), 3 deletions(-)
+
+commit 04b7b81bcbf19cb85d06d930192d6591ba45ef72
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 10:57:01 2018 +0200
+
+    Reland "Implement C++11-style GCC builtin atomic ops"
+
+    Fixed the crasher in it.
+
+ src/hb-atomic-private.hh | 22 +++++++++++++++++++---
+ src/hb-object-private.hh |  2 +-
+ 2 files changed, 20 insertions(+), 4 deletions(-)
+
+commit 019d18e9ae643134bfc3861be65ac618a5892c92
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 10:59:19 2018 +0200
+
+    Minor
+
+ src/Makefile.am      | 1 +
+ test/api/Makefile.am | 2 ++
+ 2 files changed, 3 insertions(+)
+
+commit 3edef5a19b5c0f30381ae6fe01c3370ded37f6ca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 17 10:50:01 2018 +0200
+
+    Revert "Implement C++11-style GCC builtin atomic ops"
+
+    This reverts commit 21fa170f0bfb0109c506ed17f5aff8b062564ffa.
+
+    Is crashing.  Oops.
+
+ src/hb-atomic-private.hh | 22 +++-------------------
+ src/hb-object-private.hh |  2 +-
+ 2 files changed, 4 insertions(+), 20 deletions(-)
+
+commit 21fa170f0bfb0109c506ed17f5aff8b062564ffa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 16 17:58:02 2018 +0200
+
+    Implement C++11-style GCC builtin atomic ops
+
+    Hopefully fixes bots.
+
+ src/hb-atomic-private.hh | 22 +++++++++++++++++++---
+ src/hb-object-private.hh |  2 +-
+ 2 files changed, 20 insertions(+), 4 deletions(-)
+
+commit 804b59cf4901d471253016e0cbf82cc1bbbc1d15
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 16 15:44:58 2018 +0200
+
+    Relax C++11 atomic ops memory order to acquire-release
+
+ src/hb-atomic-private.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit bda242409fc0cbb79a0ff00eba9856c4b0a9c7a1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Mon Jul 16 15:41:09 2018 +0200
+
+    Implement C++11 <atomic> operations
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/345
+
+ src/hb-atomic-private.hh          | 27 ++++++++++++++++++++++++---
+ src/hb-open-type-private.hh       |  2 +-
+ src/hb-ot-shape-complex-arabic.cc |  2 +-
+ 3 files changed, 26 insertions(+), 5 deletions(-)
+
+commit 524411224054b23bab4adad7343314df45c9c183
+Merge: 2aae617a 269eb456
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 16 14:42:43 2018 +0200
+
+    Merge pull request #1094 from anthrotype/fix-appveyor-msys2
+
+    appveyor.yml: try updating msys2 to fix failing mingw-w64-x86_64 build
+
+commit 269eb45650be66901627da7f1014339065a948a5
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 16 14:14:42 2018 +0200
+
+    appveyor.yml: try only updating msys2 core, not the rest of the
+    packages
+
+    maybe it'll get a bit faster
+
+ appveyor.yml | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit 3ab52c6cb5c405366af804d278216e2d02a39ecb
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 16 12:57:27 2018 +0200
+
+    appveyor.yml: pass --needed option to pacman
+
+    so it won't attempt reinstalling packages which are already installed
+
+ appveyor.yml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5631d70d36aa7952d343ea794bd5169a730706ae
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 16 12:41:59 2018 +0200
+
+    appveyor.yml: try updating msys2 to fix failing mingw-w64-x86_64 build
+
+    https://github.com/harfbuzz/harfbuzz/pull/1093#issuecomment-405201903
+    https://ci.appveyor.com/project/harfbuzz/harfbuzz/build/job/ky7lao1ii1bi7ew4#L71
+
+ appveyor.yml | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 2aae617a84f47836f10efd30df43e13e3a9447e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 17:27:23 2018 +0200
+
+    Move _hb_alignof later again
+
+    It uses constexpr...
+
+ src/hb-private.hh | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+commit f3a74c16ecafdca135a647ebe85117c35c1ef585
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 17:23:53 2018 +0200
+
+    Make hb_vector_t 8 bytes smaller
+
+ src/hb-dsalgs.hh | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+commit 44999f8b758374015f5d48c83f9adcb464607c2f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 17:00:59 2018 +0200
+
+    Align NullPool and CrapPool to HB_VECTOR_SIZE
+
+ src/hb-dsalgs.hh  |  3 +--
+ src/hb-private.hh | 64
+ ++++++++++++++++++++++++++++++++-----------------------
+ src/hb-static.cc  |  4 ++--
+ 3 files changed, 40 insertions(+), 31 deletions(-)
+
+commit 20a318d06acaabdee0090339dfa621aab46f1441
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 17:00:13 2018 +0200
+
+    Fix return type of alignof() fallback
+
+ src/hb-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 58cb4d9f73f1292454e3673d5e7ae5a58a566522
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 16:44:21 2018 +0200
+
+    Minor
+
+ test/api/test-ot-math.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 7796857c93b779e3c93eedd1cceb217d691dfd81
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 15:27:37 2018 +0200
+
+    Minor
+
+ RELEASING.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 2b76767bf572364d3d647cdd139f2044a7ad06b2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Wed Jul 11 15:27:13 2018 +0200
+
+    1.8.3
+
+ NEWS             | 8 ++++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+commit 718dfd4189275b1e4233dc7c12ab457352fccfcb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 16:34:31 2018 +0200
+
+    Fix shift
+
+ src/hb-dsalgs.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 25aa411ac524ed08624033da473a5e050ff41633
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 16:05:03 2018 +0200
+
+    Put back include dependencies
+
+ src/hb-object-private.hh | 2 ++
+ src/hb-private.hh        | 7 ++++---
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+commit 491d93bf74dd0483715ecca430715b69664e1211
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 16:03:31 2018 +0200
+
+    Move more stuff from hb-private.hh to hb-dsalgs.hh
+
+ src/hb-debug.hh   |   1 +
+ src/hb-dsalgs.hh  | 237
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-private.hh | 246
+ +-----------------------------------------------------
+ 3 files changed, 240 insertions(+), 244 deletions(-)
+
+commit f477765661c196ac17b2c86731881a3da36a5ae6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 15:49:05 2018 +0200
+
+    Move more stuff to hb-dsalgs.hh
+
+ src/hb-dsalgs.hh  | 83
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-private.hh | 81
+ -----------------------------------------------------
+ 2 files changed, 83 insertions(+), 81 deletions(-)
+
+commit be7f664f723fb4e7bcf15c1c2b7c6bec46f90393
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 15:23:08 2018 +0200
+
+    Move hb_bytes_t to hb-dsalgs.hh
+
+ src/hb-dsalgs.hh  | 45 ++++++++++++++++++++++++++++++++++-----------
+ src/hb-private.hh | 26 --------------------------
+ 2 files changed, 34 insertions(+), 37 deletions(-)
+
+commit 7a00f7eb2e3859db4563071934e76142bfd13916
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:42:10 2018 +0200
+
+    Remove hb_auto_array_t
+
+ src/hb-dsalgs.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit be458eb05962dd5f5c60a25f54cf0b20e7d8b055
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:41:04 2018 +0200
+
+    Include more basic internal headers from hb-private.hh
+
+ src/hb-blob-private.hh               | 2 --
+ src/hb-blob.cc                       | 1 -
+ src/hb-buffer-private.hh             | 1 -
+ src/hb-common.cc                     | 2 --
+ src/hb-coretext.cc                   | 1 -
+ src/hb-directwrite.cc                | 1 -
+ src/hb-face-private.hh               | 1 -
+ src/hb-font-private.hh               | 1 -
+ src/hb-ft.cc                         | 1 -
+ src/hb-map-private.hh                | 1 -
+ src/hb-object-private.hh             | 4 ----
+ src/hb-open-type-private.hh          | 1 -
+ src/hb-ot-layout-common-private.hh   | 1 -
+ src/hb-ot-layout-gsubgpos-private.hh | 1 -
+ src/hb-ot-shape-complex-arabic.cc    | 1 -
+ src/hb-private.hh                    | 6 +++++-
+ src/hb-set-private.hh                | 1 -
+ src/hb-shape-plan-private.hh         | 1 -
+ src/hb-shape-plan.cc                 | 1 -
+ src/hb-subset-input.cc               | 1 -
+ src/hb-subset-plan.hh                | 1 -
+ src/hb-subset.cc                     | 1 -
+ src/hb-unicode-private.hh            | 1 -
+ src/hb-uniscribe.cc                  | 1 -
+ src/hb-warning.cc                    | 4 +---
+ 25 files changed, 6 insertions(+), 32 deletions(-)
+
+commit bddeb2b10ca2f4b4bee6f7eaaf5615875a67111d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:12:37 2018 +0200
+
+    Minor renamings of internal inline functions
+
+ src/hb-buffer.cc               |  4 ++--
+ src/hb-dsalgs.hh               |  2 +-
+ src/hb-map-private.hh          |  2 +-
+ src/hb-open-type-private.hh    |  4 ++--
+ src/hb-ot-cmap-table.hh        |  2 +-
+ src/hb-ot-hdmx-table.hh        |  2 +-
+ src/hb-ot-layout-gpos-table.hh |  4 ++--
+ src/hb-ot-layout-gsub-table.hh |  2 +-
+ src/hb-ot-map.cc               |  4 ++--
+ src/hb-ot-shape.cc             |  4 ++--
+ src/hb-private.hh              | 27 ++++++++++++++-------------
+ src/hb-set-private.hh          |  6 +++---
+ src/hb-subset.cc               |  2 +-
+ 13 files changed, 33 insertions(+), 32 deletions(-)
+
+commit d652ef299d123f28409e755ed2d2411295293f19
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:05:00 2018 +0200
+
+    Move hb_vector_t and hb_lockable_set_t to hb-dsalgs.hh
+
+ src/hb-dsalgs.hh  | 311
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-private.hh | 315
+ ------------------------------------------------------
+ 2 files changed, 311 insertions(+), 315 deletions(-)
+
+commit 9e53b083295ad910a87e778ebd16cbe69ebe2130
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:03:58 2018 +0200
+
+    Move hb_stable_sort to hb-dsalgs.hh
+
+    Also, include hb-dsalgs.hh from end of hb-pricate.hh
+
+ src/hb-dsalgs.hh                | 51
+ +++++++++++++++++++++++++++++++++++++++++
+ src/hb-ot-os2-unicode-ranges.hh |  1 -
+ src/hb-ot-post-table.hh         |  1 -
+ src/hb-private.hh               | 51
+ ++---------------------------------------
+ 4 files changed, 53 insertions(+), 51 deletions(-)
+
+commit 39f11d8e72c6b2568f3b70847c6c9d1f374cd49c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 14:01:39 2018 +0200
+
+    Minor
+
+ src/hb-private.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 763f878cc0595162255c58ffe7a82ac1ca51cb0b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 13:47:41 2018 +0200
+
+    Fix syntax
+
+    Oops.
+
+ src/hb-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 83ea277178544cd7e417bdfb7b600ede94910e13
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 13:17:27 2018 +0200
+
+    Add posix_memalign() fallback
+
+ configure.ac      |  2 +-
+ src/hb-private.hh | 40 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 41 insertions(+), 1 deletion(-)
+
+commit 292c100d6141eb2e981fa632602d73768f748727
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 13:16:52 2018 +0200
+
+    Always compile (but not use) alignof() and round() fallback codes
+
+    Catches compile-errors in them better.
+
+ src/hb-private.hh | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+commit 27c5317d918971c2fb67c213621a19ac790440e4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 13:03:42 2018 +0200
+
+    Fix alignof impl
+
+ src/hb-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bca83618cda7ee4f683b4685d10db9e1bef4983c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 12:58:13 2018 +0200
+
+    Add fallback implementation for constexpr and alignof
+
+ src/hb-private.hh | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+commit 7cb47d0f3f202843ebc7fb8801bf388bb90ba3aa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 10 12:51:29 2018 +0200
+
+    Minor
+
+ src/hb-set-private.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit bf9e9676dda686f5b76826b4e3148f4a0b512e3c
+Merge: 46d8f0d5 53f73409
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 9 20:24:22 2018 +0200
+
+    Merge pull request #1091 from anthrotype/fix-gen-def-py
+
+    gen-def.py: pass headers as arguments so that msys2 can convert
+    posix paths
+
+commit 53f73409a91241765ae6a0cadf7600676988b6af
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 9 18:54:23 2018 +0100
+
+    CMakeLists.txt: don't pass header args as single space-separated
+    string
+
+    let python's parse command-line args as usual
+
+ CMakeLists.txt | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 83d2233a5c47cf1feadcdece5bd4a6b498c6ee7a
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 9 18:48:20 2018 +0100
+
+    CMakeLists.txt: pass headers as arguments to gen-def.py; call using
+    PYTHON_EXECUTABLE
+
+ CMakeLists.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit ccdd15655480fe35226c0b757e28d3527fe2e6af
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 9 18:26:44 2018 +0100
+
+    src/Makefile.am: pass headers to gen-def.py as arguments, not env vars
+
+ src/Makefile.am | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit e3a931ef0b86419b5e4ba17de51535393471ed9d
+Author: Cosimo Lupo <cosimo@anthrotype.com>
+Date:   Mon Jul 9 18:11:29 2018 +0100
+
+    gen-def.py: pass headers as arguments so that msys2 can convert
+    posix paths
+
+    When one is not using the msys2 python, the header files that are
+    passed in as environment
+    variable cannot be found.
+
+    https://ci.appveyor.com/project/fonttools/ttfautohint-py/build/1.0.65/job/rkremny4jjid9nl2#L803
+
+    This is because msys2 shell and make use POSIX paths
+    (e.g. /c/Users/clupo/...)
+    whereas non-msys2 python.exe uses native Windows paths
+    (e.g. C:\Users\clupo\...).
+
+    Msys2 will automatically convert command line arguments (but not
+    environment variables) from
+    POSIX to Windows paths when calling a native win32 executable,
+    so we pass the header paths
+    as arguments instead of environment variables.
+
+    This way the gen-def.py script can support both mingw python running
+    in an MSYS2 shell, and
+    native win32 python.
+
+ src/gen-def.py | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+commit 46d8f0d5521c3dd0b10c78e66153faefdb9046db
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Fri Jul 6 15:47:03 2018 -0400
+
+    Do not enforce a native direction of LTR for Runic
+
+    Fixes #481
+
+ src/hb-common.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 936dadc6610666aa5781e8662b859f18f9baa636
+Author: David Corbett <corbett.dav@husky.neu.edu>
+Date:   Sat Jul 7 11:08:17 2018 -0400
+
+    Regenerate the USE table for Grantha and Bhaiksuki (#1090)
+
+    Completes #1037 and fixes #1035.
+
+ src/hb-ot-shape-complex-use-table.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 1ebaa090d80bf0b59308d2c70f5e58dd8da47450
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jul 5 14:04:13 2018 +0430
+
+    Disable vectorization
+
+    Disable vectorization for now.  To correctly use them, we should
+    use posix_memalign() to allocate them.  Otherwise, can cause
+    misaligned access.
+
+    https://bugs.chromium.org/p/chromium/issues/detail?id=860184
+
+ src/hb-private.hh | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+commit 18a06f8a662ca7a9e63f74c6443e24a035c40655
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jul 5 14:03:48 2018 +0430
+
+    Fix warning
+
+    ../../src/hb-ot-layout-gsubgpos-private.hh:391:18: warning:
+    missed loop optimization, the loop counter may overflow
+    [-Wunsafe-loop-optimizations]
+
+ src/hb-ot-layout-gsubgpos-private.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 058708a665cdd9e796581dbcf60a5778d3f5e240
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Thu Jul 5 13:16:00 2018 +0430
+
+    Allow disabling vector_size use
+
+ src/hb-private.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit d8a7dedc83042c5a643195172830acf78f2e59ff
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jul 4 15:33:39 2018 +0430
+
+    Use CreateFileW explicitly and pass wchar_t to it (#1087)
+
+ src/hb-blob.cc | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+commit 9940504e933d6766f87dca7fccc3c2f889976a22
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 3 14:29:25 2018 +0430
+
+    [indic] Adjust left-matra repositioning and Halant,ZWJ sequence
+
+    From the new code (first paragraph is from the OT Devanagari spec.):
+
+      /*   o Reorder matras:
+       *
+       *     If a pre-base matra character had been reordered before
+       applying basic
+       *     features, the glyph can be moved closer to the main consonant
+       based on
+       *     whether half-forms had been formed. Actual position for
+       the matra is
+       *     defined as “after last standalone halant glyph, after
+       initial matra
+       *     position and before the main consonant”. If ZWJ or ZWNJ
+       follow this
+       *     halant, position is moved after it.
+       *
+       * IMPLEMENTATION NOTES:
+       *
+       * It looks like the last sentence is wrong.  Testing, with Windows
+       7 Uniscribe
+       * and Devanagari shows that the behavior is best described as:
+       *
+       * "If ZWJ follows this halant, matra is NOT repositioned after
+       this halant.
+       *  If ZWNJ follows this halant, position is moved after it."
+       *
+       * Test case, with Adobe Devanagari or Nirmala UI:
+       *
+       *   U+091F,U+094D,U+200C,U+092F,U+093F
+       *   (Matra moves to the middle, after ZWNJ.)
+       *
+       *   U+091F,U+094D,U+200D,U+092F,U+093F
+       *   (Matra does NOT move, stays to the left.)
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1070
+
+    Test case added with Adobe Devanagari.
+
+ src/hb-ot-shape-complex-indic.cc                   |  37
+ +++++++++++++++++++++
+ .../8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf   | Bin 0 -> 4364 bytes
+ .../data/in-house/tests/indic-joiners.tests        |   4 +++
+ 3 files changed, 41 insertions(+)
+
+commit 2cb075fe26201f3e370fccfff6c1bc242b5acc79
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 3 13:04:05 2018 +0430
+
+    Fix unused function '_hb_mapped_file_destroy' if no mmap
+
+ src/hb-blob.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 343e8c694b03eea625523229a9468fbb456e3aea
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 3 12:43:59 2018 +0430
+
+    1.8.2
+
+ NEWS             | 8 ++++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+commit 29e7879bcf3fe955a0be3bb41e929e68f39ad01e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jul 3 12:38:21 2018 +0430
+
+    Disable .dfont code for now
+
+    The get_table imple was wrong, as table offsets in a dfont are
+    relative to the resource.  We were treating them as relative to
+    the big blob itself.  To be fixed.
+
+    Part of https://github.com/harfbuzz/harfbuzz/pull/1085
+
+ src/hb-open-file-private.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 32348a43c154eac6bfb21b9e8044b38ed763601e
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jul 1 15:32:43 2018 +0430
+
+    Fix trak table apply logic
+
+    In collaboration with Behdad
+
+ src/hb-aat-layout-trak-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 225b92b7d4437360f8779850ee0aae85966679b5
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jul 1 14:32:00 2018 +0430
+
+    Support dfont font files (#949)
+
+ src/hb-open-file-private.hh | 196
+ ++++++++++++++++++++++++++++++++++++++++++++
+ src/hb-open-type-private.hh |   1 +
+ src/main.cc                 |   3 +
+ 3 files changed, 200 insertions(+)
+
+commit 5d8cafcf6a47ce73afff06499f6be23c72ab6797
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jul 1 01:54:14 2018 +0430
+
+    Improve nommap naming and use C style comments on create_from_file
+    (#1084)
+
+ .circleci/config.yml |  2 +-
+ src/hb-blob.cc       | 16 ++++++++--------
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+commit d3c0980ac234698627cb281e5526cc99139eed30
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jun 30 15:59:25 2018 +0430
+
+    Adjust MarkBasePos heuristic in presence of MultipleSubst
+
+    From the issue:
+    "In this font, the virama,ya first forms a ligature, then decomposes
+    back to
+    virama,ya. This causes those two to be marked parts of a MultipleSubst
+    sequence. When attaching the matra, we look for the first of the
+    MultipleSubst
+    sequence because that's where we attach to (because of eg #740). In
+    this case,
+    the first glyph in the MultipleSubst sequence is a mark, so we skip
+    it and
+    attach to the base char before it."
+
+    Font in question is Nirmala UI from Windows 10. Test sequence:
+
+      U+0926,U+094D,U+092F,U+0941
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1020
+
+ src/hb-ot-layout-gpos-table.hh | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+commit 8b9cbe3b24be2ae0166e682103e22ec916316ecf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jun 30 12:28:03 2018 +0430
+
+    [indic] Tweak for old-spec Bengali and halant-ya-halant
+
+    Fixes https://github.com/harfbuzz/harfbuzz/issues/1073
+
+ src/hb-ot-shape-complex-indic.cc | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+commit 9541c9dae10156fb61e4786545d1976cdcfb6bda
+Author: punchcutter <zarijoscha@gmail.com>
+Date:   Sun Jun 24 22:54:57 2018 -0700
+
+    Rebase and update USE overrides for Bhaiksuki Gap Fillers and
+    Grantha Anusvara
+
+ src/gen-use-table.py | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit 7b8dfac560abe89d48cfc2f6efb4a61820bd28bf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jun 30 09:16:54 2018 +0430
+
+    [khmer] Fix infinite-loop in cluster merging
+
+    Indic shaper already had this check.  We removed it when forking
+    Khmer shaper by mistake.
+
+    Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1464623
+
+ src/hb-ot-shape-complex-khmer.cc | 31 +++++++++++++++++--------------
+ 1 file changed, 17 insertions(+), 14 deletions(-)
+
+commit 25970a93aa6596d50ae538c6274625f95153572c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Jun 28 14:32:36 2018 +0430
+
+    armcc compatibility, don't use EINTR if doesn't exist
+
+    Fixes #1081
+
+ src/hb-blob.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 8a51f91b7035bbfaf39af1b962faf1613d2ea3b7
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Thu Jun 28 13:22:21 2018 +0430
+
+    Minor on hb_blob_create_from_file, reuse ferror result
+
+    Oops
+
+ src/hb-blob.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 71971800ed1c0501a58e6ff7730e3cebec2ef2f8
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jun 27 18:14:52 2018 +0430
+
+    [ci] Don't fail on apt update and revive clang-O3-O0
+
+ .circleci/config.yml | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7b4099f35f766d33d483a4b9d0805ef16020ea23
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jun 27 16:54:44 2018 +0430
+
+    Minor, rename blob to data on blob_from_file
+
+ src/hb-blob.cc | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit fa090ed4d47df12b2e611c9a667c398742f7e4ba
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Wed Jun 27 14:13:26 2018 +0430
+
+    Minor touches on hb_blob_create_from_file (#1079)
+
+    * Handle EINTR on fallback reader
+    * Increase fallback reader limitation size limitation to 2 << 28
+    * Ensure _O_BINARY does exist if MMAP is used on Windows
+      (maybe superfluous but makes me more confident)
+
+ src/hb-blob.cc | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+commit 01dff1ea1aa871fa19a92c2afd63c8cb5dd6e455
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jun 26 18:00:58 2018 -0400
+
+    Make round() fallback portable to systems that do have round()
+
+    Makes compiling without HAVE_ROUND on systems that do have it work.
+
+ src/hb-private.hh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7db2e9ea38329b9393c9e8cc905b180735c9b0f4
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Tue Jun 26 10:46:10 2018 +0430
+
+    Minor on hb_blob_create_from_file
+
+    Add one more "unlikely" annotation and use explicit nullptr check
+    for more consistency.
+
+ src/hb-blob.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4f8753464ae44dfb60bee81ede10448175db7b90
+Author: Garret Rieger <grieger@google.com>
+Date:   Fri Jun 22 15:29:34 2018 -0700
+
+    [subset] Add fuzzer test case that caused a timeout to the corpus.
+
+ ...testcase-minimized-hb-subset-fuzzer-5750092395970560 | Bin 0 ->
+ 72435 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 35ce8f31d37cf7c2a1f8265d36ba4c2c9a3efb2c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Jun 25 22:23:43 2018 +0430
+
+    Unify our pipe reader with the fallback reader (#1068)
+
+    And assign one bot to use the path always using NOMMAPFILEREADER
+    token.
+
+    It's limited to 200mb so no more fun with using /dev/zero on hb-view!
+
+ .circleci/config.yml |   6 +-
+ src/hb-blob.cc       | 152
+ ++++++++++++++++++++++-----------------------------
+ 2 files changed, 68 insertions(+), 90 deletions(-)
+
+commit f57804a8a596e88843ddc8b88afac7526349b89b
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Jun 25 18:45:49 2018 +0430
+
+    Resolve ttx absolute path before use (#1075)
+
+ test/subset/run-tests.py | 101
+ ++++++++++++++++++++++++++---------------------
+ 1 file changed, 57 insertions(+), 44 deletions(-)
+
+commit 159ddb872986f121818e816d2ea75d271075ba1f
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jun 24 23:09:16 2018 +0430
+
+    Treat - just as /dev/stdin and remove one extra file reader (#1065)
+
+ util/options.cc | 27 +++++++++------------------
+ 1 file changed, 9 insertions(+), 18 deletions(-)
+
+commit b2a187918757a0faaf0f564ec2b0766c09fa364c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Sat Jun 23 10:32:28 2018 -0400
+
+    In Coverage iterator, bail out if table smells
+
+    In particular, if CoverageFormat2 has unsorted ranges, bail out.
+    Otherwise, 64k ranges of each 64k glyphs can DoS closure() method.
+
+    We can do the same for CoverageFormat1, but that one does not expose
+    the quadratic behavior, so, fine.
+
+ src/hb-ot-layout-common-private.hh | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+commit 941f2b85489b344698bf036922c589483034a7f2
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Jun 18 20:35:40 2018 +0430
+
+    Support pipe and friends on hb_blob_create_from_file (#1061)
+
+    With this hb-view/hb-shape support pipes and possibly socket and
+    named pipe
+    also, anything fails just on mmap.
+
+    We can later do the same for Windows also.
+
+    This however reveals two issues, the fact most of our bots don't
+    have HAVE_MMAP and using
+    this instead the other fread/fopen reader can make failure on CI. I
+    should look at them separately
+    this change however is very low risk I believe.
+
+ src/hb-blob.cc | 44 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 43 insertions(+), 1 deletion(-)
+
+commit d0c2889dfc43da92c76d6eab5482b1298744dc9c
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Mon Jun 18 19:59:33 2018 +0430
+
+    Revert file blob sanitization and index checking (#1062)
+
+    As
+    https://github.com/harfbuzz/harfbuzz/pull/1059#issuecomment-397912812
+    we
+    like to still work with blobs that harfbuzz itself can't handle
+    directly that are failing sanitization
+    currently apparently.
+
+ util/options.cc | 12 ++----------
+ util/options.hh |  2 +-
+ 2 files changed, 3 insertions(+), 11 deletions(-)
+
+commit c53697d3f2a3fae8b68ec4c5146c7000a07e0963
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jun 17 17:04:55 2018 +0430
+
+    Verbose fail when something is wrong with hb-shape/hb-view input
+    font file (#1059)
+
+    This checks if the blob isn't empty and uses `hb_face_count`
+    to see if the font file passes the simple font file sanitization
+    so can detect if the input is actually a font and checks also
+    whether input font-index is out of range.
+
+ util/options.cc | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+commit aa0c5df4199ef4e96df2b856c8f629e49fdd5120
+Author: Ebrahim Byagowi <ebrahim@gnu.org>
+Date:   Sun Jun 17 16:49:34 2018 +0430
+
+    Fix reading fonts from stdin (#1060)
+
+    We were passing the font path directly to freetype so rendering
+    was broken when we are getting the font from stdin.
+
+    This fixes it by using FT_New_Memory_Face instead.
+
+    This fixes:
+    * build/util/hb-view /dev/stdin text < font.ttf
+    * build/util/hb-view - text < font.ttf
+    * cat font.ttf | build/util/hb-view - text
+
+    but doesn't work on
+    * cat font.ttf | build/util/hb-view /dev/stdin text
+
+    which I will try to fix separately.
+
+ util/helper-cairo.cc | 14 ++++++++++----
+ util/options.cc      |  5 ++---
+ util/options.hh      |  4 +++-
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+commit 3654d9be6b017e66307fe0ffe635266938b14702
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date:   Tue Jun 12 19:38:04 2018 -0400
+
+    1.8.1
+
+ NEWS             | 8 ++++++++
+ configure.ac     | 2 +-
+ src/hb-version.h | 4 ++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
 commit f3e58ab8a957cdf36bddef793c473664744885a7
 Author: Behdad Esfahbod <behdad@behdad.org>
 Date:   Tue Jun 12 19:32:04 2018 -0400
index 7ea6386..6faf227 100644 (file)
@@ -96,8 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
@@ -328,6 +327,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
diff --git a/NEWS b/NEWS
index 12010bd..ef87dad 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,341 @@
+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
 ====================================
@@ -5,6 +343,7 @@ Tuesday, June 12, 2018
 - 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
 ====================================
diff --git a/README b/README
index 55775c8..fd93be8 100644 (file)
--- a/README
+++ b/README
@@ -1,9 +1,10 @@
-[![Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg)](https://travis-ci.org/harfbuzz/harfbuzz)
-[![Build status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
-[![CircleCI](https://circleci.com/gh/harfbuzz/harfbuzz.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz)
-[![Coverity](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
-[![Coverage Status](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
+[![Travis Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg?branch=master)](https://travis-ci.org/harfbuzz/harfbuzz)
+[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true&branch=master)](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
+[![CircleCI Build Status](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz/tree/master)
+[![Coverity Code Health](https://img.shields.io/coverity/scan/5450.svg)](https://scan.coverity.com/projects/behdad-harfbuzz)
+[![Codacy Code Health](https://api.codacy.com/project/badge/Grade/f17f1708783c447488bc8dd317150eaa)](https://app.codacy.com/app/behdad/harfbuzz)
+[![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/master/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz)
+[![Coverals Code Coverage](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz)
 [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
 
 This is HarfBuzz, a text shaping library.
index 4c0ba9b..7cf091a 100644 (file)
@@ -23,7 +23,7 @@ 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 interpretter:
+import works in your Python interpreter:
 
 ```python
 from gi.repository import HarfBuzz
index 851d2bf..799eb63 100644 (file)
@@ -1,6 +1,6 @@
 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
-implemenetation and that specially is important where OpenType specification
+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:
 
@@ -27,8 +27,8 @@ steps are recommended:
 Now you can use hb-shape using `wine winbuild/util/hb-shape.exe` but if you like to
 to use the original Uniscribe,
 
-8. Bring a 32bit version of `usp10.dll` for youself from `C:\Windows\SysWOW64\usp10.dll` of your
-   Windows installation (asuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
+8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
+   Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
    that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
    Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
    it is designed to work with DirectWrite which Wine can't work with its original one.
index 0aef610..1fd8365 100644 (file)
@@ -8,7 +8,8 @@ HarfBuzz release walk-through checklist:
      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
+     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.
@@ -25,11 +26,17 @@ HarfBuzz release walk-through checklist:
 
 6. Do "make distcheck", if it passes, you get a tarball.
    Otherwise, fix things and commit them separately before making release,
+   Note: Check src/hb-version.h and make sure the new version number is
+   there.  Sometimes, it does not get updated.  If that's the case,
+   "touch configure.ac" and rebuild.  Also check that there is no hb-version.h
+   in your build/src file. Typically it will fail the distcheck if there is.
+   That's what happened to 2.0.0 going out with 1.8.0 hb-version.h...  So, that's
+   a clue.
 
 7. "make release-files".  Enter your GPG password.  This creates a sha256 hash
    and signs it.
 
-8. Now that you have release files built, commit NEWS and configure.ac changes,
+8. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
    as well as any REPLACEME changes you made.  The commit message is simply the
    release number.  Eg. "1.4.7"
 
diff --git a/TODO b/TODO
index 6dac0be..d8e4105 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,9 +1,3 @@
-General fixes:
-=============
-
-- Implement 'rand' feature.
-
-
 API issues:
 ===========
 
@@ -19,11 +13,7 @@ API additions
 
 - Add hb-cairo glue
 
-- Add sanitize API (and a cached version, that saves result on blob user-data)
-
-- BCP 47 language handling / API (language_matches?)
-
-- Add hb_font_create_unscaled()?
+- Add sanitize API.
 
 - Add query / enumeration API for aalt-like features?
 
index 178d1c5..ecde363 100644 (file)
@@ -117,6 +117,282 @@ AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
   _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
 ])
 
+dnl pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+dnl serial 11 (pkg-config-0.29)
+dnl
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes ],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+       AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+       AC_MSG_RESULT([no])
+       m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
 # Copyright (C) 2002-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
@@ -1316,4 +1592,3 @@ m4_include([m4/ltoptions.m4])
 m4_include([m4/ltsugar.m4])
 m4_include([m4/ltversion.m4])
 m4_include([m4/lt~obsolete.m4])
-m4_include([m4/pkg.m4])
index 2e9ad7f..31e01ef 100755 (executable)
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2016 Free Software Foundation, Inc.
+#   Copyright 1992-2017 Free Software Foundation, Inc.
 
-timestamp='2016-10-02'
+timestamp='2017-11-07'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@ timestamp='2016-10-02'
 # 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 <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -27,7 +27,7 @@ timestamp='2016-10-02'
 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 #
 # Please send patches to <config-patches@gnu.org>.
 
@@ -39,7 +39,7 @@ Usage: $0 [OPTION]
 
 Output the configuration name of the system \`$me' is run on.
 
-Operation modes:
+Options:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -50,7 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2017 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -244,6 +244,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
        echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
        exit ;;
+    *:MidnightBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE}
+       exit ;;
     *:ekkoBSD:*:*)
        echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
        exit ;;
@@ -259,6 +262,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:Sortix:*:*)
        echo ${UNAME_MACHINE}-unknown-sortix
        exit ;;
+    *:Redox:*:*)
+       echo ${UNAME_MACHINE}-unknown-redox
+       exit ;;
     alpha:OSF1:*:*)
        case $UNAME_RELEASE in
        *4.0)
@@ -315,15 +321,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        exitcode=$?
        trap '' 0
        exit $exitcode ;;
-    Alpha\ *:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # Should we change UNAME_MACHINE based on the output of uname instead
-       # of the specific Alpha model?
-       echo alpha-pc-interix
-       exit ;;
-    21064:Windows_NT:50:3)
-       echo alpha-dec-winnt3.5
-       exit ;;
     Amiga*:UNIX_System_V:4.0:*)
        echo m68k-unknown-sysv4
        exit ;;
@@ -485,13 +482,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 #endif
        #if defined (host_mips) && defined (MIPSEB)
        #if defined (SYSTYPE_SYSV)
-         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
        #endif
        #if defined (SYSTYPE_SVR4)
-         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
        #endif
        #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+         printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
        #endif
        #endif
          exit (-1);
@@ -614,7 +611,7 @@ EOF
     *:AIX:*:*)
        echo rs6000-ibm-aix
        exit ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
        echo romp-ibm-bsd4.4
        exit ;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
@@ -635,8 +632,8 @@ EOF
     9000/[34678]??:HP-UX:*:*)
        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        case "${UNAME_MACHINE}" in
-           9000/31? )            HP_ARCH=m68000 ;;
-           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/31?)            HP_ARCH=m68000 ;;
+           9000/[34]??)         HP_ARCH=m68k ;;
            9000/[678][0-9][0-9])
                if [ -x /usr/bin/getconf ]; then
                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
@@ -749,7 +746,7 @@ EOF
                { echo "$SYSTEM_NAME"; exit; }
        echo unknown-hitachi-hiuxwe2
        exit ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
        echo hppa1.1-hp-bsd
        exit ;;
     9000/8??:4.3bsd:*:*)
@@ -758,7 +755,7 @@ EOF
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
        echo hppa1.0-hp-mpeix
        exit ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
        echo hppa1.1-hp-osf
        exit ;;
     hp8??:OSF1:*:*)
@@ -837,10 +834,11 @@ EOF
        UNAME_PROCESSOR=`/usr/bin/uname -p`
        case ${UNAME_PROCESSOR} in
            amd64)
-               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-           *)
-               echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+               UNAME_PROCESSOR=x86_64 ;;
+           i386)
+               UNAME_PROCESSOR=i586 ;;
        esac
+       echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
@@ -854,10 +852,6 @@ EOF
     *:MSYS*:*)
        echo ${UNAME_MACHINE}-pc-msys
        exit ;;
-    i*:windows32*:*)
-       # uname -m includes "-pc" on this system.
-       echo ${UNAME_MACHINE}-mingw32
-       exit ;;
     i*:PW*:*)
        echo ${UNAME_MACHINE}-pc-pw32
        exit ;;
@@ -873,27 +867,12 @@ EOF
                echo ia64-unknown-interix${UNAME_RELEASE}
                exit ;;
        esac ;;
-    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
-       echo i${UNAME_MACHINE}-pc-mks
-       exit ;;
-    8664:Windows_NT:*)
-       echo x86_64-pc-mks
-       exit ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-       # UNAME_MACHINE based on the output of uname instead of i386?
-       echo i586-pc-interix
-       exit ;;
     i*:UWIN*:*)
        echo ${UNAME_MACHINE}-pc-uwin
        exit ;;
     amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
        echo x86_64-unknown-cygwin
        exit ;;
-    p*:CYGWIN*:*)
-       echo powerpcle-unknown-cygwin
-       exit ;;
     prep*:SunOS:5.*:*)
        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
        exit ;;
@@ -1096,7 +1075,7 @@ EOF
     i*86:*DOS:*:*)
        echo ${UNAME_MACHINE}-pc-msdosdjgpp
        exit ;;
-    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+    i*86:*:4.*:*)
        UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
                echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
@@ -1303,14 +1282,21 @@ EOF
        if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
            if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
                if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-                   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-                   grep IS_64BIT_ARCH >/dev/null
+                      (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+                      grep IS_64BIT_ARCH >/dev/null
                then
                    case $UNAME_PROCESSOR in
                        i386) UNAME_PROCESSOR=x86_64 ;;
                        powerpc) UNAME_PROCESSOR=powerpc64 ;;
                    esac
                fi
+               # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+               if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+                      (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+                      grep IS_PPC >/dev/null
+               then
+                   UNAME_PROCESSOR=powerpc
+               fi
            fi
        elif test "$UNAME_PROCESSOR" = i386 ; then
            # Avoid executing cc on OS X 10.9, as it ships with a stub
@@ -1334,15 +1320,18 @@ EOF
     *:QNX:*:4*)
        echo i386-pc-qnx
        exit ;;
-    NEO-?:NONSTOP_KERNEL:*:*)
+    NEO-*:NONSTOP_KERNEL:*:*)
        echo neo-tandem-nsk${UNAME_RELEASE}
        exit ;;
     NSE-*:NONSTOP_KERNEL:*:*)
        echo nse-tandem-nsk${UNAME_RELEASE}
        exit ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
+    NSR-*:NONSTOP_KERNEL:*:*)
        echo nsr-tandem-nsk${UNAME_RELEASE}
        exit ;;
+    NSX-*:NONSTOP_KERNEL:*:*)
+       echo nsx-tandem-nsk${UNAME_RELEASE}
+       exit ;;
     *:NonStop-UX:*:*)
        echo mips-compaq-nonstopux
        exit ;;
@@ -1414,16 +1403,28 @@ EOF
        exit ;;
 esac
 
+echo "$0: unable to guess system type" >&2
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in
+    mips:Linux | mips64:Linux)
+       # If we got here on MIPS GNU/Linux, output extra information.
+       cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+       ;;
+esac
+
 cat >&2 <<EOF
-$0: unable to guess system type
 
 This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite
-config.guess and config.sub with the latest versions from:
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
 
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 and
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 If $0 has already been updated, send the following data and any
 information you think might be pertinent to config-patches@gnu.org to
@@ -1455,7 +1456,7 @@ EOF
 exit 1
 
 # Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'write-file-functions 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
index c52ceb9..7faa9fd 100644 (file)
@@ -85,8 +85,8 @@
 /* Define to 1 if you have the `newlocale' function. */
 #undef HAVE_NEWLOCALE
 
-/* Have native OpenType Layout backend */
-#undef HAVE_OT
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
 
 /* Have POSIX threads */
 #undef HAVE_PTHREAD
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# undef _ALL_SOURCE
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# undef _GNU_SOURCE
-#endif
-/* Enable threading extensions on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
 /* Enable large inode numbers on Mac OS X 10.5.  */
 #ifndef _DARWIN_USE_64_BIT_INODE
 # define _DARWIN_USE_64_BIT_INODE 1
 
 /* Define for large files, on AIX-style hosts. */
 #undef _LARGE_FILES
-
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
-   this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
index dd2ca93..00f68b8 100755 (executable)
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2016 Free Software Foundation, Inc.
+#   Copyright 1992-2017 Free Software Foundation, Inc.
 
-timestamp='2016-11-04'
+timestamp='2017-11-23'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@ timestamp='2016-11-04'
 # 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 <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -33,7 +33,7 @@ timestamp='2016-11-04'
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
 
 Canonicalize a configuration name.
 
-Operation modes:
+Options:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2017 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -229,9 +229,6 @@ case $os in
        -ptx*)
                basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
                ;;
-       -windowsnt*)
-               os=`echo $os | sed -e 's/windowsnt/winnt/'`
-               ;;
        -psos*)
                os=-psos
                ;;
@@ -263,7 +260,7 @@ case $basic_machine in
        | fido | fr30 | frv | ft32 \
        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
        | hexagon \
-       | i370 | i860 | i960 | ia64 \
+       | i370 | i860 | i960 | ia16 | ia64 \
        | ip2k | iq2000 \
        | k1om \
        | le32 | le64 \
@@ -315,7 +312,7 @@ case $basic_machine in
        | ubicom32 \
        | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
        | visium \
-       | we32k \
+       | wasm32 \
        | x86 | xc16x | xstormy16 | xtensa \
        | z8k | z80)
                basic_machine=$basic_machine-unknown
@@ -388,7 +385,7 @@ case $basic_machine in
        | h8300-* | h8500-* \
        | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
        | hexagon-* \
-       | i*86-* | i860-* | i960-* | ia64-* \
+       | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
        | ip2k-* | iq2000-* \
        | k1om-* \
        | le32-* | le64-* \
@@ -446,6 +443,7 @@ case $basic_machine in
        | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
        | vax-* \
        | visium-* \
+       | wasm32-* \
        | we32k-* \
        | x86-* | x86_64-* | xc16x-* | xps100-* \
        | xstormy16-* | xtensa*-* \
@@ -641,7 +639,7 @@ case $basic_machine in
                basic_machine=rs6000-bull
                os=-bosx
                ;;
-       dpx2* | dpx2*-bull)
+       dpx2*)
                basic_machine=m68k-bull
                os=-sysv3
                ;;
@@ -903,7 +901,7 @@ case $basic_machine in
                basic_machine=v70-nec
                os=-sysv
                ;;
-       next | m*-next )
+       next | m*-next)
                basic_machine=m68k-next
                case $os in
                    -nextstep* )
@@ -948,6 +946,9 @@ case $basic_machine in
        nsr-tandem)
                basic_machine=nsr-tandem
                ;;
+       nsx-tandem)
+               basic_machine=nsx-tandem
+               ;;
        op50n-* | op60c-*)
                basic_machine=hppa1.1-oki
                os=-proelf
@@ -1243,6 +1244,9 @@ case $basic_machine in
                basic_machine=a29k-wrs
                os=-vxworks
                ;;
+       wasm32)
+               basic_machine=wasm32-unknown
+               ;;
        w65*)
                basic_machine=w65-wdc
                os=-none
@@ -1251,6 +1255,9 @@ case $basic_machine in
                basic_machine=hppa1.1-winbond
                os=-proelf
                ;;
+       x64)
+               basic_machine=x86_64-pc
+               ;;
        xbox)
                basic_machine=i686-pc
                os=-mingw32
@@ -1358,8 +1365,8 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-       # First match some system type aliases
-       # that might get confused with valid system types.
+       # First match some system type aliases that might get confused
+       # with valid system types.
        # -solaris* is a basic system type, with this one exception.
        -auroraux)
                os=-auroraux
@@ -1379,9 +1386,9 @@ case $os in
        -gnu/linux*)
                os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
                ;;
-       # First accept the basic system types.
+       # Now accept the basic system types.
        # The portable systems comes first.
-       # Each alternative MUST END IN A *, to match a version number.
+       # Each alternative MUST end in a * to match a version number.
        # -sysv* is not here because it comes later, after sysvr4.
        -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
              | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
@@ -1397,7 +1404,7 @@ case $os in
              | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
              | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
              | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
              | -linux-newlib* | -linux-musl* | -linux-uclibc* \
@@ -1409,7 +1416,7 @@ case $os in
              | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
              | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
              | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
-             | -onefs* | -tirtos* | -phoenix* | -fuchsia*)
+             | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
        -qnx*)
@@ -1484,7 +1491,7 @@ case $os in
        -nova*)
                os=-rtmk-nova
                ;;
-       -ns2 )
+       -ns2)
                os=-nextstep2
                ;;
        -nsk*)
@@ -1539,6 +1546,19 @@ case $os in
        -dicos*)
                os=-dicos
                ;;
+       -pikeos*)
+               # Until real need of OS specific support for
+               # particular features comes up, bare metal
+               # configurations are quite functional.
+               case $basic_machine in
+                   arm*)
+                       os=-eabi
+                       ;;
+                   *)
+                       os=-elf
+                       ;;
+               esac
+               ;;
        -nacl*)
                ;;
        -ios)
@@ -1638,6 +1658,9 @@ case $basic_machine in
        sparc-* | *-sun)
                os=-sunos4.1.1
                ;;
+       pru-*)
+               os=-elf
+               ;;
        *-be)
                os=-beos
                ;;
@@ -1683,7 +1706,7 @@ case $basic_machine in
        m88k-omron*)
                os=-luna
                ;;
-       *-next )
+       *-next)
                os=-nextstep
                ;;
        *-sequent)
@@ -1818,7 +1841,7 @@ echo $basic_machine$os
 exit
 
 # Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'write-file-functions 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
index bd784a3..54a04a1 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for HarfBuzz 1.8.1.
+# Generated by GNU Autoconf 2.69 for HarfBuzz 2.3.1.
 #
 # Report bugs to <https://github.com/harfbuzz/harfbuzz/issues/new>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='HarfBuzz'
 PACKAGE_TARNAME='harfbuzz'
-PACKAGE_VERSION='1.8.1'
-PACKAGE_STRING='HarfBuzz 1.8.1'
+PACKAGE_VERSION='2.3.1'
+PACKAGE_STRING='HarfBuzz 2.3.1'
 PACKAGE_BUGREPORT='https://github.com/harfbuzz/harfbuzz/issues/new'
 PACKAGE_URL='http://harfbuzz.org/'
 
@@ -702,8 +702,6 @@ GLIB_CFLAGS
 GLIB_DEPS
 HAVE_FALLBACK_FALSE
 HAVE_FALLBACK_TRUE
-HAVE_OT_FALSE
-HAVE_OT_TRUE
 HAVE_PTHREAD_FALSE
 HAVE_PTHREAD_TRUE
 PTHREAD_CFLAGS
@@ -742,6 +740,8 @@ HB_VERSION_MINOR
 HB_VERSION_MAJOR
 GIT
 RAGEL
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
 PKG_CONFIG
 CXXCPP
 am__fastdepCXX_FALSE
@@ -925,6 +925,8 @@ CXXFLAGS
 CCC
 CXXCPP
 PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
 GTKDOC_DEPS_CFLAGS
 GTKDOC_DEPS_LIBS
 GLIB_CFLAGS
@@ -1493,7 +1495,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures HarfBuzz 1.8.1 to adapt to many kinds of systems.
+\`configure' configures HarfBuzz 2.3.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1564,7 +1566,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of HarfBuzz 1.8.1:";;
+     short | recursive ) echo "Configuration of HarfBuzz 2.3.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1644,6 +1646,10 @@ Some influential environment variables:
   CXXFLAGS    C++ compiler flags
   CXXCPP      C++ preprocessor
   PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
   GTKDOC_DEPS_CFLAGS
               C compiler flags for GTKDOC_DEPS, overriding pkg-config
   GTKDOC_DEPS_LIBS
@@ -1743,7 +1749,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-HarfBuzz configure 1.8.1
+HarfBuzz configure 2.3.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2018,97 +2024,6 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_func
 
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval \${$3+:} false; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_header_compiler=yes
-else
-  ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  ac_header_preproc=yes
-else
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
-  yes:no: )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-    ;;
-  no:yes:* )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( $as_echo "## -------------------------------------------------------------- ##
-## Report this to https://github.com/harfbuzz/harfbuzz/issues/new ##
-## -------------------------------------------------------------- ##"
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
 # ac_fn_cxx_try_compile LINENO
 # ----------------------------
 # Try to compile conftest.$ac_ext, and return whether this succeeded.
@@ -2276,6 +2191,97 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_decl
 
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## -------------------------------------------------------------- ##
+## Report this to https://github.com/harfbuzz/harfbuzz/issues/new ##
+## -------------------------------------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
 # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
 # --------------------------------------------
 # Tries to find the compile-time value of EXPR in a program that includes
@@ -2607,7 +2613,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by HarfBuzz $as_me 1.8.1, which was
+It was created by HarfBuzz $as_me 2.3.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3476,7 +3482,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='harfbuzz'
- VERSION='1.8.1'
+ VERSION='2.3.1'
 
 
 # Some tools Automake needs.
@@ -13453,67 +13459,6 @@ CC=$lt_save_CC
 
 
 # Check for programs
-
-  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
-if test "x$ac_cv_header_minix_config_h" = xyes; then :
-  MINIX=yes
-else
-  MINIX=
-fi
-
-
-  if test "$MINIX" = yes; then
-
-$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
-
-
-$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
-
-
-$as_echo "#define _MINIX 1" >>confdefs.h
-
-  fi
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
-$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
-if ${ac_cv_safe_to_define___extensions__+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#         define __EXTENSIONS__ 1
-          $ac_includes_default
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_safe_to_define___extensions__=yes
-else
-  ac_cv_safe_to_define___extensions__=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
-$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
-  test $ac_cv_safe_to_define___extensions__ = yes &&
-    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
-
-  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
-
-  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
-
-  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
-
-  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
-
-
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 
 
 
+
+
+
+
+
 if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
        if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
@@ -18447,7 +18397,6 @@ $as_echo "yes" >&6; }
 $as_echo "no" >&6; }
                PKG_CONFIG=""
        fi
-
 fi
 
 RAGEL=${RAGEL-"${am_missing_run}ragel"}
@@ -18461,10 +18410,10 @@ GIT=${GIT-"${am_missing_run}git"}
 
 
 
-HB_VERSION_MAJOR=1
-HB_VERSION_MINOR=8
+HB_VERSION_MAJOR=2
+HB_VERSION_MINOR=3
 HB_VERSION_MICRO=1
-HB_VERSION=1.8.1
+HB_VERSION=2.3.1
 
 
 
@@ -18475,7 +18424,7 @@ HB_VERSION=1.8.1
 
 
 
-HB_LIBTOOL_VERSION_INFO=10800:1:10800
+HB_LIBTOOL_VERSION_INFO=20301:0:20301
 
 
 
@@ -18727,46 +18676,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5
 $as_echo_n "checking for GTKDOC_DEPS... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GTKDOC_DEPS_CFLAGS"; then
-        pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GTKDOC_DEPS_CFLAGS"; then
+    pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GTKDOC_DEPS_LIBS"; then
-        pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GTKDOC_DEPS_LIBS"; then
+    pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -18774,24 +18723,24 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0"`
+               GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0" 2>&1`
         else
-               GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0"`
+               GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GTKDOC_DEPS_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS
        GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-       :
+
 fi
   fi
 
@@ -18874,7 +18823,7 @@ fi
 
 
 # Functions and headers
-for ac_func in atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l
+for ac_func in atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -19014,9 +18963,6 @@ fi
        # by overriding CXXFLAGS.
        CXXFLAGS="-fno-rtti $CXXFLAGS -fno-exceptions -fno-threadsafe-statics"
 
-       # Assorted warnings
-       CXXFLAGS="$CXXFLAGS -Wcast-align"
-
        case "$host" in
                *-*-mingw*)
                ;;
 
 
 
-have_ot=true
-if $have_ot; then
-
-$as_echo "#define HAVE_OT 1" >>confdefs.h
-
-fi
- if $have_ot; then
-  HAVE_OT_TRUE=
-  HAVE_OT_FALSE='#'
-else
-  HAVE_OT_TRUE='#'
-  HAVE_OT_FALSE=
-fi
-
-
 have_fallback=true
 if $have_fallback; then
 
@@ -19769,46 +19700,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5
 $as_echo_n "checking for GLIB... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GLIB_CFLAGS"; then
-        pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GLIB_CFLAGS"; then
+    pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GLIB_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$GLIB_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "$GLIB_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GLIB_LIBS"; then
-        pkg_cv_GLIB_LIBS="$GLIB_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GLIB_LIBS"; then
+    pkg_cv_GLIB_LIBS="$GLIB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GLIB_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$GLIB_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "$GLIB_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -19816,17 +19747,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$GLIB_DEPS"`
+               GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GLIB_DEPS" 2>&1`
         else
-               GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$GLIB_DEPS"`
+               GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GLIB_DEPS" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GLIB_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
@@ -19869,46 +19800,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GOBJECT" >&5
 $as_echo_n "checking for GOBJECT... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GOBJECT_CFLAGS"; then
-        pkg_cv_GOBJECT_CFLAGS="$GOBJECT_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GOBJECT_CFLAGS"; then
+    pkg_cv_GOBJECT_CFLAGS="$GOBJECT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-2.0 glib-2.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "gobject-2.0 glib-2.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GOBJECT_CFLAGS=`$PKG_CONFIG --cflags "gobject-2.0 glib-2.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GOBJECT_LIBS"; then
-        pkg_cv_GOBJECT_LIBS="$GOBJECT_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GOBJECT_LIBS"; then
+    pkg_cv_GOBJECT_LIBS="$GOBJECT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-2.0 glib-2.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "gobject-2.0 glib-2.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GOBJECT_LIBS=`$PKG_CONFIG --libs "gobject-2.0 glib-2.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -19916,17 +19847,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gobject-2.0 glib-2.0"`
+               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gobject-2.0 glib-2.0" 2>&1`
         else
-               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gobject-2.0 glib-2.0"`
+               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gobject-2.0 glib-2.0" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GOBJECT_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        GOBJECT_CFLAGS=$pkg_cv_GOBJECT_CFLAGS
@@ -20087,46 +20018,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAIRO" >&5
 $as_echo_n "checking for CAIRO... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$CAIRO_CFLAGS"; then
-        pkg_cv_CAIRO_CFLAGS="$CAIRO_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$CAIRO_CFLAGS"; then
+    pkg_cv_CAIRO_CFLAGS="$CAIRO_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo >= 1.8.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "cairo >= 1.8.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_CAIRO_CFLAGS=`$PKG_CONFIG --cflags "cairo >= 1.8.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$CAIRO_LIBS"; then
-        pkg_cv_CAIRO_LIBS="$CAIRO_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$CAIRO_LIBS"; then
+    pkg_cv_CAIRO_LIBS="$CAIRO_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo >= 1.8.0\""; } >&5
   ($PKG_CONFIG --exists --print-errors "cairo >= 1.8.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_CAIRO_LIBS=`$PKG_CONFIG --libs "cairo >= 1.8.0" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20134,17 +20065,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               CAIRO_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "cairo >= 1.8.0"`
+               CAIRO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cairo >= 1.8.0" 2>&1`
         else
-               CAIRO_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "cairo >= 1.8.0"`
+               CAIRO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cairo >= 1.8.0" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$CAIRO_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        CAIRO_CFLAGS=$pkg_cv_CAIRO_CFLAGS
@@ -20178,46 +20109,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAIRO_FT" >&5
 $as_echo_n "checking for CAIRO_FT... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$CAIRO_FT_CFLAGS"; then
-        pkg_cv_CAIRO_FT_CFLAGS="$CAIRO_FT_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$CAIRO_FT_CFLAGS"; then
+    pkg_cv_CAIRO_FT_CFLAGS="$CAIRO_FT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo-ft\""; } >&5
   ($PKG_CONFIG --exists --print-errors "cairo-ft") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_CAIRO_FT_CFLAGS=`$PKG_CONFIG --cflags "cairo-ft" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$CAIRO_FT_LIBS"; then
-        pkg_cv_CAIRO_FT_LIBS="$CAIRO_FT_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$CAIRO_FT_LIBS"; then
+    pkg_cv_CAIRO_FT_LIBS="$CAIRO_FT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cairo-ft\""; } >&5
   ($PKG_CONFIG --exists --print-errors "cairo-ft") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_CAIRO_FT_LIBS=`$PKG_CONFIG --libs "cairo-ft" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20225,17 +20156,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               CAIRO_FT_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "cairo-ft"`
+               CAIRO_FT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cairo-ft" 2>&1`
         else
-               CAIRO_FT_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "cairo-ft"`
+               CAIRO_FT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cairo-ft" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$CAIRO_FT_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        CAIRO_FT_CFLAGS=$pkg_cv_CAIRO_FT_CFLAGS
@@ -20275,46 +20206,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FONTCONFIG" >&5
 $as_echo_n "checking for FONTCONFIG... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$FONTCONFIG_CFLAGS"; then
-        pkg_cv_FONTCONFIG_CFLAGS="$FONTCONFIG_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$FONTCONFIG_CFLAGS"; then
+    pkg_cv_FONTCONFIG_CFLAGS="$FONTCONFIG_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fontconfig\""; } >&5
   ($PKG_CONFIG --exists --print-errors "fontconfig") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_FONTCONFIG_CFLAGS=`$PKG_CONFIG --cflags "fontconfig" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$FONTCONFIG_LIBS"; then
-        pkg_cv_FONTCONFIG_LIBS="$FONTCONFIG_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$FONTCONFIG_LIBS"; then
+    pkg_cv_FONTCONFIG_LIBS="$FONTCONFIG_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fontconfig\""; } >&5
   ($PKG_CONFIG --exists --print-errors "fontconfig") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_FONTCONFIG_LIBS=`$PKG_CONFIG --libs "fontconfig" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20322,17 +20253,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               FONTCONFIG_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "fontconfig"`
+               FONTCONFIG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "fontconfig" 2>&1`
         else
-               FONTCONFIG_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "fontconfig"`
+               FONTCONFIG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "fontconfig" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$FONTCONFIG_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        FONTCONFIG_CFLAGS=$pkg_cv_FONTCONFIG_CFLAGS
@@ -20375,46 +20306,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ICU" >&5
 $as_echo_n "checking for ICU... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$ICU_CFLAGS"; then
-        pkg_cv_ICU_CFLAGS="$ICU_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$ICU_CFLAGS"; then
+    pkg_cv_ICU_CFLAGS="$ICU_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"icu-uc\""; } >&5
   ($PKG_CONFIG --exists --print-errors "icu-uc") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_ICU_CFLAGS=`$PKG_CONFIG --cflags "icu-uc" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$ICU_LIBS"; then
-        pkg_cv_ICU_LIBS="$ICU_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$ICU_LIBS"; then
+    pkg_cv_ICU_LIBS="$ICU_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"icu-uc\""; } >&5
   ($PKG_CONFIG --exists --print-errors "icu-uc") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_ICU_LIBS=`$PKG_CONFIG --libs "icu-uc" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20422,17 +20353,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               ICU_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "icu-uc"`
+               ICU_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "icu-uc" 2>&1`
         else
-               ICU_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "icu-uc"`
+               ICU_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "icu-uc" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$ICU_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        ICU_CFLAGS=$pkg_cv_ICU_CFLAGS
@@ -20623,7 +20554,7 @@ else
 fi
 
 have_graphite2=false
-GRAPHITE2_DEPS="graphite2"
+GRAPHITE2_DEPS="graphite2 >= 1.2.0"
 
 if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
 
@@ -20631,46 +20562,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GRAPHITE2" >&5
 $as_echo_n "checking for GRAPHITE2... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GRAPHITE2_CFLAGS"; then
-        pkg_cv_GRAPHITE2_CFLAGS="$GRAPHITE2_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GRAPHITE2_CFLAGS"; then
+    pkg_cv_GRAPHITE2_CFLAGS="$GRAPHITE2_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GRAPHITE2_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$GRAPHITE2_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GRAPHITE2_CFLAGS=`$PKG_CONFIG --cflags "$GRAPHITE2_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GRAPHITE2_LIBS"; then
-        pkg_cv_GRAPHITE2_LIBS="$GRAPHITE2_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$GRAPHITE2_LIBS"; then
+    pkg_cv_GRAPHITE2_LIBS="$GRAPHITE2_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GRAPHITE2_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$GRAPHITE2_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_GRAPHITE2_LIBS=`$PKG_CONFIG --libs "$GRAPHITE2_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20678,17 +20609,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GRAPHITE2_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$GRAPHITE2_DEPS"`
+               GRAPHITE2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GRAPHITE2_DEPS" 2>&1`
         else
-               GRAPHITE2_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$GRAPHITE2_DEPS"`
+               GRAPHITE2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GRAPHITE2_DEPS" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GRAPHITE2_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        GRAPHITE2_CFLAGS=$pkg_cv_GRAPHITE2_CFLAGS
@@ -20751,46 +20682,46 @@ pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FREETYPE" >&5
 $as_echo_n "checking for FREETYPE... " >&6; }
 
-if test -n "$PKG_CONFIG"; then
-    if test -n "$FREETYPE_CFLAGS"; then
-        pkg_cv_FREETYPE_CFLAGS="$FREETYPE_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$FREETYPE_CFLAGS"; then
+    pkg_cv_FREETYPE_CFLAGS="$FREETYPE_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$FREETYPE_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$FREETYPE_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_FREETYPE_CFLAGS=`$PKG_CONFIG --cflags "$FREETYPE_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$FREETYPE_LIBS"; then
-        pkg_cv_FREETYPE_LIBS="$FREETYPE_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
+if test -n "$FREETYPE_LIBS"; then
+    pkg_cv_FREETYPE_LIBS="$FREETYPE_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
     { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$FREETYPE_DEPS\""; } >&5
   ($PKG_CONFIG --exists --print-errors "$FREETYPE_DEPS") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_FREETYPE_LIBS=`$PKG_CONFIG --libs "$FREETYPE_DEPS" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
-    fi
-else
-       pkg_failed=untried
+ else
+    pkg_failed=untried
 fi
 
 
 
 if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
         _pkg_short_errors_supported=yes
@@ -20798,17 +20729,17 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               FREETYPE_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$FREETYPE_DEPS"`
+               FREETYPE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FREETYPE_DEPS" 2>&1`
         else
-               FREETYPE_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$FREETYPE_DEPS"`
+               FREETYPE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FREETYPE_DEPS" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$FREETYPE_PKG_ERRORS" >&5
 
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-                :
+       :
 elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
        :
 else
        FREETYPE_CFLAGS=$pkg_cv_FREETYPE_CFLAGS
@@ -21170,7 +21101,7 @@ fi
 fi
 
 
-ac_config_files="$ac_config_files Makefile src/Makefile src/harfbuzz-config.cmake src/hb-ucdn/Makefile util/Makefile test/Makefile test/api/Makefile test/fuzzing/Makefile test/shaping/Makefile test/shaping/data/Makefile test/shaping/data/in-house/Makefile test/shaping/data/text-rendering-tests/Makefile test/subset/Makefile test/subset/data/Makefile docs/Makefile docs/version.xml"
+ac_config_files="$ac_config_files Makefile src/Makefile src/harfbuzz-config.cmake src/hb-ucdn/Makefile util/Makefile test/Makefile test/api/Makefile test/fuzzing/Makefile test/shaping/Makefile test/shaping/data/Makefile test/shaping/data/aots/Makefile test/shaping/data/in-house/Makefile test/shaping/data/text-rendering-tests/Makefile test/subset/Makefile test/subset/data/Makefile docs/Makefile docs/version.xml"
 
 
 cat >confcache <<\_ACEOF
@@ -21358,10 +21289,6 @@ if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then
   as_fn_error $? "conditional \"HAVE_PTHREAD\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_OT_TRUE}" && test -z "${HAVE_OT_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_OT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${HAVE_FALLBACK_TRUE}" && test -z "${HAVE_FALLBACK_FALSE}"; then
   as_fn_error $? "conditional \"HAVE_FALLBACK\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -21823,7 +21750,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by HarfBuzz $as_me 1.8.1, which was
+This file was extended by HarfBuzz $as_me 2.3.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21890,7 +21817,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-HarfBuzz config.status 1.8.1
+HarfBuzz config.status 2.3.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -22413,6 +22340,7 @@ do
     "test/fuzzing/Makefile") CONFIG_FILES="$CONFIG_FILES test/fuzzing/Makefile" ;;
     "test/shaping/Makefile") CONFIG_FILES="$CONFIG_FILES test/shaping/Makefile" ;;
     "test/shaping/data/Makefile") CONFIG_FILES="$CONFIG_FILES test/shaping/data/Makefile" ;;
+    "test/shaping/data/aots/Makefile") CONFIG_FILES="$CONFIG_FILES test/shaping/data/aots/Makefile" ;;
     "test/shaping/data/in-house/Makefile") CONFIG_FILES="$CONFIG_FILES test/shaping/data/in-house/Makefile" ;;
     "test/shaping/data/text-rendering-tests/Makefile") CONFIG_FILES="$CONFIG_FILES test/shaping/data/text-rendering-tests/Makefile" ;;
     "test/subset/Makefile") CONFIG_FILES="$CONFIG_FILES test/subset/Makefile" ;;
index 13cd1ce..b7827a6 100644 (file)
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.8.1],
+        [2.3.1],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -19,7 +19,6 @@ LT_PREREQ([2.2])
 LT_INIT([disable-static])
 
 # Check for programs
-AC_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
 AC_PROG_CC_C99
 AM_PROG_CC_C_O
@@ -78,7 +77,7 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
 ])
 
 # Functions and headers
-AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign)
 
 save_libs="$LIBS"
 LIBS="$LIBS -lm"
@@ -103,9 +102,6 @@ if test "x$GCC" = "xyes"; then
        # by overriding CXXFLAGS.
        CXXFLAGS="-fno-rtti $CXXFLAGS -fno-exceptions -fno-threadsafe-statics"
 
-       # Assorted warnings
-       CXXFLAGS="$CXXFLAGS -Wcast-align"
-
        case "$host" in
                *-*-mingw*)
                ;;
@@ -148,12 +144,6 @@ AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
 
 dnl ==========================================================================
 
-have_ot=true
-if $have_ot; then
-       AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend])
-fi
-AM_CONDITIONAL(HAVE_OT, $have_ot)
-
 have_fallback=true
 if $have_fallback; then
        AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])
@@ -330,7 +320,7 @@ AC_ARG_WITH(graphite2,
                        [Use the graphite2 library @<:@default=no@:>@])],,
        [with_graphite2=no])
 have_graphite2=false
-GRAPHITE2_DEPS="graphite2"
+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, :)
@@ -514,6 +504,7 @@ test/api/Makefile
 test/fuzzing/Makefile
 test/shaping/Makefile
 test/shaping/data/Makefile
+test/shaping/data/aots/Makefile
 test/shaping/data/in-house/Makefile
 test/shaping/data/text-rendering-tests/Makefile
 test/subset/Makefile
index a993538..9b54b40 100644 (file)
@@ -62,7 +62,6 @@ 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
-EXTRA_HFILES=$(top_builddir)/src/hb-version.h
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
@@ -73,14 +72,15 @@ HTML_IMAGES=  \
 # 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-shaping-concepts.xml \
        usermanual-buffers-language-script-and-direction.xml \
-       usermanual-clusters.xml \
        usermanual-fonts-and-faces.xml \
-       usermanual-glyph-information.xml \
-       usermanual-hello-harfbuzz.xml \
-       usermanual-install-harfbuzz.xml \
+       usermanual-clusters.xml \
        usermanual-opentype-features.xml \
-       usermanual-what-is-harfbuzz.xml \
+       usermanual-glyph-information.xml \
        version.xml
 
 # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
index 100c353..3e2825e 100644 (file)
@@ -104,8 +104,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -253,6 +252,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -382,7 +383,6 @@ 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
-EXTRA_HFILES = $(top_builddir)/src/hb-version.h
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
@@ -394,14 +394,15 @@ HTML_IMAGES = \
 # 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-shaping-concepts.xml \
        usermanual-buffers-language-script-and-direction.xml \
-       usermanual-clusters.xml \
        usermanual-fonts-and-faces.xml \
-       usermanual-glyph-information.xml \
-       usermanual-hello-harfbuzz.xml \
-       usermanual-install-harfbuzz.xml \
+       usermanual-clusters.xml \
        usermanual-opentype-features.xml \
-       usermanual-what-is-harfbuzz.xml \
+       usermanual-glyph-information.xml \
        version.xml
 
 
@@ -809,6 +810,7 @@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_con
          if test -f $(abs_builddir)/$$file ; then \
            cp $(abs_builddir)/$$file $(abs_builddir)/html; \
          fi; \
+         test -f $$file && cp $$file $(abs_builddir)/html; \
        done;
        $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
        $(AM_V_at)touch html-build.stamp
index 9452a92..2735338 100644 (file)
       <graphic fileref="HarfBuzz.png" format="PNG" align="center"/>
       <para>
         HarfBuzz is an <ulink url="http://www.microsoft.com/typography/otspec/">OpenType</ulink>
-        text shaping engine.
-      </para>
-      <para>
-        The current HarfBuzz codebase, formerly known as harfbuzz-ng, is
-        versioned 1.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. The canonical
-        source tree is available
-        <ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
-        Also available on
-        <ulink url="https://github.com/harfbuzz/harfbuzz">github</ulink>.
-        See <xref linkend="download" endterm="download.title"/> for release tarballs.
+        text shaping engine. 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 old HarfBuzz codebase, these days known as harfbuzz-old, was
-        derived from <ulink url="http://freetype.org/">FreeType</ulink>,
-        <ulink url="http://pango.org/">Pango</ulink>, and
-        <ulink url="http://qt-project.org/">Qt</ulink> and is available
-        <ulink url="http://cgit.freedesktop.org/harfbuzz.old/">here</ulink>.
-        It is not actively developed or maintained, and is extremely buggy. All
-        users are encouraged to switch over to the new HarfBuzz as soon as
-        possible.  There are no release tarballs of old HarfBuzz whatsoever.
+       The canonical source-code tree is available at
+        <ulink
+           url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>
+        and is also available at
+        <ulink
+           url="http://cgit.freedesktop.org/harfbuzz/">cgit.freedesktop.org/harfbuzz</ulink>.
+       See <xref linkend="download" endterm="download.title"/> for
+       release tarballs.
       </para>
     </abstract>
   </bookinfo>
@@ -42,7 +35,8 @@
     <title>User's manual</title>
       <xi:include href="usermanual-what-is-harfbuzz.xml"/>
       <xi:include href="usermanual-install-harfbuzz.xml"/>
-      <xi:include href="usermanual-hello-harfbuzz.xml"/>
+      <xi:include href="usermanual-getting-started.xml"/>
+      <xi:include href="usermanual-shaping-concepts.xml"/>
       <xi:include href="usermanual-buffers-language-script-and-direction.xml"/>
       <xi:include href="usermanual-fonts-and-faces.xml"/>
       <xi:include href="usermanual-clusters.xml"/>
         <ulink role="online-location" url="http://[SERVER]/libharfbuzz/index.html">http://[SERVER]/libharfbuzz/</ulink>.-->
       </releaseinfo>
     </partinfo>
+
+    <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>
+      
     <title>Reference manual</title>
       <chapter>
-        <title>HarfBuzz API</title>
-        <xi:include href="xml/hb.xml"/>
-        <xi:include href="xml/hb-common.xml"/>
-        <xi:include href="xml/hb-unicode.xml"/>
-        <xi:include href="xml/hb-buffer.xml"/>
+        <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-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"/>
-        <xi:include href="xml/hb-deprecated.xml"/>
-
-        <xi:include href="xml/hb-set.xml"/>
+      </chapter>
 
-        <xi:include href="xml/hb-ot.xml"/>
-        <xi:include href="xml/hb-ot-layout.xml"/>
-        <xi:include href="xml/hb-ot-tag.xml"/>
+      <chapter>
+        <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-shape.xml"/>
+        <xi:include href="xml/hb-ot-layout.xml"/>
         <xi:include href="xml/hb-ot-math.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>
 
-        <xi:include href="xml/hb-shape-plan.xml"/>
-
-        <xi:include href="xml/hb-glib.xml"/>
-        <xi:include href="xml/hb-icu.xml"/>
+      <chapter>
+        <title>Apple Advanced Typography API</title>
+        <xi:include href="xml/hb-aat-layout.xml"/>
+      </chapter>
 
+      <chapter>
+        <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-gobject.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-coretext.xml"/>
-
-        <xi:include href="xml/hb-gobject.xml"/>
-
       </chapter>
-      <chapter id="object-tree">
+
+      <!--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="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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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="deprecated-api-index" role="deprecated">
-        <title>Index of deprecated API</title>
-        <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
-      </index>
+      </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-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-5" role="1.7.5"><title>Index of new symbols in 1.7.5</title><xi:include href="xml/api-index-1.7.5.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-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-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-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>
 
       <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
   </part>
index 5715d77..fd7682e 100644 (file)
@@ -1,8 +1,20 @@
-<SECTION>
-<FILE>hb</FILE>
 <SUBSECTION Private>
 HB_H_IN
-HB_EXTERN
+HB_OT_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>
@@ -67,6 +79,8 @@ hb_buffer_set_user_data
 hb_buffer_get_user_data
 hb_buffer_get_glyph_infos
 hb_buffer_get_glyph_positions
+hb_buffer_get_invisible_glyph
+hb_buffer_set_invisible_glyph
 hb_buffer_set_replacement_codepoint
 hb_buffer_get_replacement_codepoint
 hb_buffer_normalize_glyphs
@@ -144,6 +158,10 @@ uint16_t
 uint32_t
 uint64_t
 uint8_t
+<SUBSECTION Private>
+HB_EXTERN
+HB_DEPRECATED
+HB_DEPRECATED_FOR
 </SECTION>
 
 <SECTION>
@@ -153,7 +171,30 @@ HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
 HB_SCRIPT_CANADIAN_ABORIGINAL
 hb_font_funcs_set_glyph_func
 hb_font_get_glyph_func_t
+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_set_invert
+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_h_kerning_func
+hb_font_funcs_set_glyph_v_kerning_func
+hb_font_get_glyph_h_kerning
+hb_font_get_glyph_h_kerning_func_t
+hb_font_get_glyph_kerning_for_direction
+hb_font_get_glyph_kerning_func_t
+hb_font_get_glyph_v_kerning
+hb_font_get_glyph_v_kerning_func_t
 </SECTION>
 
 <SECTION>
@@ -170,6 +211,7 @@ hb_coretext_font_get_ct_font
 <SECTION>
 <FILE>hb-face</FILE>
 hb_face_count
+hb_face_t
 hb_face_create
 hb_face_create_for_tables
 hb_face_destroy
@@ -188,7 +230,11 @@ hb_face_set_glyph_count
 hb_face_set_index
 hb_face_set_upem
 hb_face_set_user_data
-hb_face_t
+hb_face_collect_unicodes
+hb_face_collect_variation_selectors
+hb_face_collect_variation_unicodes
+hb_face_builder_create
+hb_face_builder_add_table
 </SECTION>
 
 <SECTION>
@@ -208,13 +254,14 @@ 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_kerning_func
+hb_font_funcs_set_glyph_h_advances_func
 hb_font_funcs_set_glyph_h_origin_func
 hb_font_funcs_set_glyph_name_func
 hb_font_funcs_set_glyph_v_advance_func
-hb_font_funcs_set_glyph_v_kerning_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
@@ -223,6 +270,8 @@ 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
@@ -233,24 +282,24 @@ 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_kerning
-hb_font_get_glyph_h_kerning_func_t
+hb_font_get_glyph_h_advances
+hb_font_get_glyph_h_advances_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_v_advance
 hb_font_get_glyph_v_advance_func_t
-hb_font_get_glyph_v_kerning
-hb_font_get_glyph_v_kerning_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
@@ -327,7 +376,9 @@ HB_GOBJECT_TYPE_FACE
 HB_GOBJECT_TYPE_FONT
 HB_GOBJECT_TYPE_FONT_FUNCS
 HB_GOBJECT_TYPE_GLYPH_FLAGS
+HB_GOBJECT_TYPE_MAP
 HB_GOBJECT_TYPE_MEMORY_MODE
+HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS
 HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
 HB_GOBJECT_TYPE_OT_MATH_CONSTANT
 HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART
@@ -358,7 +409,9 @@ hb_gobject_face_get_type
 hb_gobject_font_funcs_get_type
 hb_gobject_font_get_type
 hb_gobject_glyph_flags_get_type
+hb_gobject_map_get_type
 hb_gobject_memory_mode_get_type
+hb_gobject_ot_color_palette_flags_get_type
 hb_gobject_ot_layout_glyph_class_get_type
 hb_gobject_ot_math_constant_get_type
 hb_gobject_ot_math_glyph_part_get_type
@@ -382,11 +435,6 @@ HB_GOBJECT_H_IN
 </SECTION>
 
 <SECTION>
-<FILE>hb-gobject</FILE>
-
-</SECTION>
-
-<SECTION>
 <FILE>hb-graphite2</FILE>
 HB_GRAPHITE2_TAG_SILF
 hb_graphite2_face_get_gr_face
@@ -421,9 +469,27 @@ hb_map_t
 </SECTION>
 
 <SECTION>
-<FILE>hb-ot</FILE>
-<SUBSECTION Private>
-HB_OT_H_IN
+<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>
@@ -432,22 +498,40 @@ hb_ot_font_set_funcs
 </SECTION>
 
 <SECTION>
-<FILE>hb-ot-shape</FILE>
-hb_ot_shape_glyphs_closure
+<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_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_glyph_class
@@ -469,12 +553,12 @@ 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_table_choose_script
+hb_ot_layout_script_select_language
 hb_ot_layout_table_find_feature_variations
-hb_ot_layout_table_find_script
 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
 <SUBSECTION Private>
@@ -484,23 +568,6 @@ Xhb_ot_layout_lookup_substitute
 </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_NO_AXIS_INDEX
-hb_ot_var_axis_t
-hb_ot_var_has_data
-hb_ot_var_find_axis
-hb_ot_var_get_axis_count
-hb_ot_var_get_axes
-hb_ot_var_normalize_variations
-hb_ot_var_normalize_coords
-</SECTION>
-
-<SECTION>
 <FILE>hb-ot-math</FILE>
 HB_OT_TAG_MATH
 HB_OT_MATH_SCRIPT
@@ -521,13 +588,29 @@ hb_ot_math_get_glyph_assembly
 </SECTION>
 
 <SECTION>
-<FILE>hb-ot-tag</FILE>
-HB_OT_TAG_DEFAULT_LANGUAGE
-HB_OT_TAG_DEFAULT_SCRIPT
-hb_ot_tag_from_language
-hb_ot_tag_to_language
-hb_ot_tag_to_script
-hb_ot_tags_from_script
+<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>
@@ -566,6 +649,8 @@ hb_set_union
 
 <SECTION>
 <FILE>hb-shape</FILE>
+HB_FEATURE_GLOBAL_END
+HB_FEATURE_GLOBAL_START
 hb_feature_t
 hb_feature_from_string
 hb_feature_to_string
@@ -592,16 +677,14 @@ hb_shape_plan_t
 
 <SECTION>
 <FILE>hb-unicode</FILE>
-HB_UNICODE_MAX_DECOMPOSITION_LEN
+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_compatibility
 hb_unicode_decompose_func_t
-hb_unicode_eastasian_width
 hb_unicode_funcs_create
 hb_unicode_funcs_destroy
 hb_unicode_funcs_get_default
@@ -613,9 +696,7 @@ 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_compatibility_func
 hb_unicode_funcs_set_decompose_func
-hb_unicode_funcs_set_eastasian_width_func
 hb_unicode_funcs_set_general_category_func
 hb_unicode_funcs_set_mirroring_func
 hb_unicode_funcs_set_script_func
index 462211c..bd87111 100644 (file)
@@ -1,3 +1,5 @@
+hb_gobject_aat_layout_feature_selector_get_type
+hb_gobject_aat_layout_feature_type_get_type
 hb_gobject_blob_get_type
 hb_gobject_buffer_cluster_level_get_type
 hb_gobject_buffer_content_type_get_type
@@ -14,13 +16,16 @@ hb_gobject_font_get_type
 hb_gobject_glyph_flags_get_type
 hb_gobject_glyph_info_get_type
 hb_gobject_glyph_position_get_type
+hb_gobject_map_get_type
 hb_gobject_memory_mode_get_type
+hb_gobject_ot_color_palette_flags_get_type
 hb_gobject_ot_layout_glyph_class_get_type
 hb_gobject_ot_math_constant_get_type
 hb_gobject_ot_math_glyph_part_flags_get_type
 hb_gobject_ot_math_glyph_part_get_type
 hb_gobject_ot_math_glyph_variant_get_type
 hb_gobject_ot_math_kern_get_type
+hb_gobject_ot_var_axis_flags_get_type
 hb_gobject_script_get_type
 hb_gobject_segment_properties_get_type
 hb_gobject_set_get_type
index 2d953d3..714859a 100644 (file)
@@ -5,10 +5,10 @@
 <title>A clustering example for levels 0 and 1: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="clusters.html" title="">
-<link rel="prev" href="clusters.html" title="">
+<link rel="up" href="clusters.html" title="Clusters">
+<link rel="prev" href="working-with-harfbuzz-clusters.html" title="Working with HarfBuzz clusters">
 <link rel="next" href="reordering-in-levels-0-and-1.html" title="Reordering in levels 0 and 1">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="clusters.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="clusters.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="p" href="working-with-harfbuzz-clusters.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="reordering-in-levels-0-and-1.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
-<div class="sect1">
+<div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="a-clustering-example-for-levels-0-and-1"></a>A clustering example for levels 0 and 1</h2></div></div></div>
 <p>
-    Let's say we start with the following character sequence and cluster
-    values:
-  </p>
+      The basic shaping operations affect clusters in a predictable
+      manner when using level 0 or level 1: 
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>
+         When two or more clusters <span class="emphasis"><em>merge</em></span>, the
+         resulting merged cluster takes as its cluster value the
+         <span class="emphasis"><em>minimum</em></span> of the incoming cluster values.
+       </p></li>
+<li class="listitem"><p>
+         When a cluster <span class="emphasis"><em>decomposes</em></span>, all of the
+         resulting child clusters inherit as their cluster value the
+         cluster value of the parent cluster.
+       </p></li>
+<li class="listitem"><p>
+         When a character is <span class="emphasis"><em>reordered</em></span>, the
+         reordered character and all clusters that the character
+         moves past as part of the reordering are merged into one cluster.
+       </p></li>
+</ul></div>
+<p>
+      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.
+    </p>
+<p>
+      Let's say we start with the following character sequence (top row) and
+      initial cluster values (bottom row):
+    </p>
 <pre class="programlisting">
-   A,B,C,D,E
-   0,1,2,3,4
-</pre>
+      A,B,C,D,E
+      0,1,2,3,4
+    </pre>
 <p>
-    We then map the characters to glyphs. For simplicity, let's assume
-    that each character maps to the corresponding, identical-looking
-    glyph:
-  </p>
+      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:
+    </p>
 <pre class="programlisting">
-   A,B,C,D,E
-   0,1,2,3,4
-</pre>
+      A,B,C,D,E
+      0,1,2,3,4
+    </pre>
 <p>
-    Now if, for example, <code class="literal">B</code> and <code class="literal">C</code>
-    ligate, then the clusters to which they belong "merge".
-    This merged cluster takes for its cluster number the minimum of all
-    the cluster numbers of the clusters that went in. In this case, we
-    get:
-  </p>
+      Now if, for example, <code class="literal">B</code> and <code class="literal">C</code>
+      form a ligature, then the clusters to which they belong
+      "merge". 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:
+    </p>
 <pre class="programlisting">
-   A,BC,D,E
-   0,1 ,3,4
-</pre>
+      A,BC,D,E
+      0,1 ,3,4
+    </pre>
 <p>
-    Now let's assume that the <code class="literal">BC</code> glyph decomposes
-    into three components, and <code class="literal">D</code> also decomposes into
-    two. The components each inherit the cluster value of their parent:
-  </p>
+      because 1 is the minimum of the set {1,2}, which were the
+      cluster values of <code class="literal">B</code> and
+      <code class="literal">C</code>. 
+    </p>
+<p>
+      Next, let us say that the <code class="literal">BC</code> ligature glyph
+      decomposes into three components, and <code class="literal">D</code> also
+      decomposes into two components. Whenever a cluster decomposes,
+      its components each inherit the cluster value of their parent: 
+    </p>
 <pre class="programlisting">
-   A,BC0,BC1,BC2,D0,D1,E
-   0,1  ,1  ,1  ,3 ,3 ,4
-</pre>
+      A,BC0,BC1,BC2,D0,D1,E
+      0,1  ,1  ,1  ,3 ,3 ,4
+    </pre>
 <p>
-    Now if <code class="literal">BC2</code> and <code class="literal">D0</code> ligate, then
-    their clusters (numbers 1 and 3) merge into
-    <code class="literal">min(1,3) = 1</code>:
-  </p>
+      Next, if <code class="literal">BC2</code> and <code class="literal">D0</code> form a
+      ligature, then their clusters (cluster values 1 and 3) merge into
+      <code class="literal">min(1,3) = 1</code>:
+    </p>
 <pre class="programlisting">
-   A,BC0,BC1,BC2D0,D1,E
-   0,1  ,1  ,1    ,1 ,4
-</pre>
+      A,BC0,BC1,BC2D0,D1,E
+      0,1  ,1  ,1    ,1 ,4
+    </pre>
+<p>
+      Note that the entirety of cluster 3 merges into cluster 1, not
+      just the <code class="literal">D0</code> glyph. This reflects the fact
+      that the cluster <span class="emphasis"><em>must</em></span> be treated as an
+      indivisible unit.
+    </p>
 <p>
-    At this point, cluster 1 means: the character sequence
-    <code class="literal">BCD</code> is represented by glyphs
-    <code class="literal">BC0,BC1,BC2D0,D1</code> and cannot be broken down any
-    further.
-  </p>
+      At this point, cluster 1 means: the character sequence
+      <code class="literal">BCD</code> is represented by glyphs
+      <code class="literal">BC0,BC1,BC2D0,D1</code> and cannot be broken down any
+      further.
+    </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/aat-shaping.html b/docs/html/aat-shaping.html
new file mode 100644 (file)
index 0000000..e1fff44
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>AAT shaping: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="graphite-shaping.html" title="Graphite shaping">
+<link rel="next" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="graphite-shaping.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="buffers-language-script-and-direction.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="aat-shaping"></a>AAT shaping</h2></div></div></div>
+<p>
+      In contrast to OpenType shaping, AAT shaping does not specify a 
+      predefined set of shaping models or a set of supported scripts.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      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.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index dac5fa1..b1157fb 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
 <link rel="prev" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
 <link rel="next" href="setting-buffer-properties.html" title="Setting buffer properties">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -30,6 +30,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 452944b..acf5467 100644 (file)
@@ -6,8 +6,8 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="deprecated-api-index.html" title="Index of deprecated API">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-2.html" title="Index of new symbols in 0.9.2">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -31,7 +31,7 @@
                   <a class="shortcut" href="#glsT">T</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="deprecated-api-index.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="p" href="api-index-0-9-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><img src="right-insensitive.png" width="16" height="16" border="0"></td>
 </tr></table>
 <div class="glossary">
@@ -58,6 +58,8 @@
 <dt><span class="glossterm"><a name="annotation-glossterm-nullable"></a>nullable</span></dt>
 <dd class="glossdef"><p>NULL may be passed as the value in, out, in-out; or as a return value.</p></dd>
 <a name="glsO"></a><h3 class="title">O</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-optional"></a>optional</span></dt>
+<dd class="glossdef"><p>NULL may be passed instead of a pointer to a location.</p></dd>
 <dt><span class="glossterm"><a name="annotation-glossterm-out"></a>out</span></dt>
 <dd class="glossdef"><p>Parameter for returning results. Default is <acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>.</p></dd>
 <dt><span class="glossterm"><a name="annotation-glossterm-out%20caller-allocates"></a>out caller-allocates</span></dt>
@@ -74,6 +76,6 @@
 <dd class="glossdef"><p>Don't free data after the code is done.</p></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 8e20a6e..b670ca5 100644 (file)
@@ -6,20 +6,18 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-8.html" title="Index of new symbols in 0.9.8">
-<link rel="next" href="api-index-0-9-11.html" title="Index of new symbols in 0.9.11">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-11.html" title="Index of new symbols in 0.9.11">
+<link rel="next" href="api-index-0-9-8.html" title="Index of new symbols in 0.9.8">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a>
-                     <span class="dim">|</span> 
-                  <a class="shortcut" href="#idxS">S</a></span></td>
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-8.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-11.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-11.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-8.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-get-size-params" title="hb_ot_layout_get_size_params ()">hb_ot_layout_get_size_params</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
-<a name="idxS"></a><h3 class="title">S</h3>
-<dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-set-invert" title="hb_set_invert ()">hb_set_invert</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
-</dt>
-<dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 93491db..4f604c0 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-10.html" title="Index of new symbols in 0.9.10">
-<link rel="next" href="api-index-0-9-20.html" title="Index of new symbols in 0.9.20">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-20.html" title="Index of new symbols in 0.9.20">
+<link rel="next" href="api-index-0-9-10.html" title="Index of new symbols in 0.9.10">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-10.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-20.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-20.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-10.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-11"></a>Index of new symbols in 0.9.11</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index b6c781d..921e090 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-full.html" title="API Index">
-<link rel="next" href="api-index-0-9-5.html" title="Index of new symbols in 0.9.5">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-5.html" title="Index of new symbols in 0.9.5">
+<link rel="next" href="annotation-glossary.html" title="Annotation Glossary">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -34,8 +34,8 @@
                   <a class="shortcut" href="#idxV">V</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-full.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="annotation-glossary.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxD"></a><h3 class="title">D</h3>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-func" title="hb_font_funcs_set_glyph_func ()">hb_font_funcs_set_glyph_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advance-func" title="hb_font_funcs_set_glyph_h_advance_func ()">hb_font_funcs_set_glyph_h_advance_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a>, function in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <a name="idxS"></a><h3 class="title">S</h3>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape" title="hb_shape ()">hb_shape</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()">hb_shape</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <a name="idxT"></a><h3 class="title">T</h3>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-decompose-compatibility" title="hb_unicode_decompose_compatibility ()">hb_unicode_decompose_compatibility</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-eastasian-width" title="hb_unicode_eastasian_width ()">hb_unicode_eastasian_width</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-create" title="hb_unicode_funcs_create ()">hb_unicode_funcs_create</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-compatibility-func" title="hb_unicode_funcs_set_decompose_compatibility_func ()">hb_unicode_funcs_set_decompose_compatibility_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-func" title="hb_unicode_funcs_set_decompose_func ()">hb_unicode_funcs_set_decompose_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-eastasian-width-func" title="hb_unicode_funcs_set_eastasian_width_func ()">hb_unicode_funcs_set_eastasian_width_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-general-category-func" title="hb_unicode_funcs_set_general_category_func ()">hb_unicode_funcs_set_general_category_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 5e237d7..290acb6 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-11.html" title="Index of new symbols in 0.9.11">
-<link rel="next" href="api-index-0-9-22.html" title="Index of new symbols in 0.9.22">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-22.html" title="Index of new symbols in 0.9.22">
+<link rel="next" href="api-index-0-9-11.html" title="Index of new symbols in 0.9.11">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-11.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-22.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-22.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-11.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-20"></a>Index of new symbols in 0.9.20</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 68ce10b..7e56b79 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-20.html" title="Index of new symbols in 0.9.20">
-<link rel="next" href="api-index-0-9-28.html" title="Index of new symbols in 0.9.28">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-28.html" title="Index of new symbols in 0.9.28">
+<link rel="next" href="api-index-0-9-20.html" title="Index of new symbols in 0.9.20">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-20.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-28.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-28.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-20.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -29,6 +29,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index bff8406..1fa3ea2 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-22.html" title="Index of new symbols in 0.9.22">
-<link rel="next" href="api-index-0-9-30.html" title="Index of new symbols in 0.9.30">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-30.html" title="Index of new symbols in 0.9.30">
+<link rel="next" href="api-index-0-9-22.html" title="Index of new symbols in 0.9.22">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-22.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-30.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-30.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-22.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -29,6 +29,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 96983c9..863701e 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-28.html" title="Index of new symbols in 0.9.28">
-<link rel="next" href="api-index-0-9-31.html" title="Index of new symbols in 0.9.31">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-31.html" title="Index of new symbols in 0.9.31">
+<link rel="next" href="api-index-0-9-28.html" title="Index of new symbols in 0.9.28">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -18,8 +18,8 @@
                   <a class="shortcut" href="#idxV">V</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-28.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-31.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-31.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-28.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -36,6 +36,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index b169c5a..7326017 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-30.html" title="Index of new symbols in 0.9.30">
-<link rel="next" href="api-index-0-9-38.html" title="Index of new symbols in 0.9.38">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-38.html" title="Index of new symbols in 0.9.38">
+<link rel="next" href="api-index-0-9-30.html" title="Index of new symbols in 0.9.30">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-30.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-38.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-38.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-30.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-31"></a>Index of new symbols in 0.9.31</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a>, macro in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a>, macro in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index d992efc..196a9cc 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-31.html" title="Index of new symbols in 0.9.31">
-<link rel="next" href="api-index-0-9-39.html" title="Index of new symbols in 0.9.39">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-39.html" title="Index of new symbols in 0.9.39">
+<link rel="next" href="api-index-0-9-31.html" title="Index of new symbols in 0.9.31">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -18,8 +18,8 @@
                   <a class="shortcut" href="#idxG">G</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-31.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-39.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-39.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-31.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -40,6 +40,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index af17300..91f6acc 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-38.html" title="Index of new symbols in 0.9.38">
-<link rel="next" href="api-index-0-9-41.html" title="Index of new symbols in 0.9.41">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-41.html" title="Index of new symbols in 0.9.41">
+<link rel="next" href="api-index-0-9-38.html" title="Index of new symbols in 0.9.38">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-38.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-41.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-41.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-38.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-39"></a>Index of new symbols in 0.9.39</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 92a80e0..b5913e9 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-39.html" title="Index of new symbols in 0.9.39">
-<link rel="next" href="api-index-0-9-42.html" title="Index of new symbols in 0.9.42">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-42.html" title="Index of new symbols in 0.9.42">
+<link rel="next" href="api-index-0-9-39.html" title="Index of new symbols in 0.9.39">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-39.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-42.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-42.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-39.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-41"></a>Index of new symbols in 0.9.41</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index fe8cd8c..b048b2d 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-41.html" title="Index of new symbols in 0.9.41">
-<link rel="next" href="api-index-1-0-5.html" title="Index of new symbols in 1.0.5">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-0-5.html" title="Index of new symbols in 1.0.5">
+<link rel="next" href="api-index-0-9-41.html" title="Index of new symbols in 0.9.41">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-41.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-0-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-0-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-41.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-42"></a>Index of new symbols in 0.9.42</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index f1801c5..9054ab0 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-2.html" title="Index of new symbols in 0.9.2">
-<link rel="next" href="api-index-0-9-7.html" title="Index of new symbols in 0.9.7">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-7.html" title="Index of new symbols in 0.9.7">
+<link rel="next" href="api-index-0-9-2.html" title="Index of new symbols in 0.9.2">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a class="shortcut" href="#idxT">T</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-7.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-7.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-5"></a>Index of new symbols in 0.9.5</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxF"></a><h3 class="title">F</h3>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <a name="idxT"></a><h3 class="title">T</h3>
@@ -51,6 +51,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index e6b8ee2..8ffe5dd 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-5.html" title="Index of new symbols in 0.9.5">
-<link rel="next" href="api-index-0-9-8.html" title="Index of new symbols in 0.9.8">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-8.html" title="Index of new symbols in 0.9.8">
+<link rel="next" href="api-index-0-9-5.html" title="Index of new symbols in 0.9.5">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a class="shortcut" href="#idxS">S</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-8.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-8.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-0-9-7"></a>Index of new symbols in 0.9.7</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxF"></a><h3 class="title">F</h3>
 <dd></dd>
 <a name="idxS"></a><h3 class="title">S</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index bf22b18..c42dee8 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-7.html" title="Index of new symbols in 0.9.7">
-<link rel="next" href="api-index-0-9-10.html" title="Index of new symbols in 0.9.10">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-0-9-10.html" title="Index of new symbols in 0.9.10">
+<link rel="next" href="api-index-0-9-7.html" title="Index of new symbols in 0.9.7">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-7.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-10.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-0-9-10.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-7.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -29,6 +29,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 805ef95..47bc601 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-0-9-42.html" title="Index of new symbols in 0.9.42">
-<link rel="next" href="api-index-1-1-2.html" title="Index of new symbols in 1.1.2">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-1-2.html" title="Index of new symbols in 1.1.2">
+<link rel="next" href="api-index-0-9-42.html" title="Index of new symbols in 0.9.42">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-0-9-42.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-1-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-1-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-0-9-42.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -37,6 +37,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 0b57389..5a774cc 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-0-5.html" title="Index of new symbols in 1.0.5">
-<link rel="next" href="api-index-1-1-3.html" title="Index of new symbols in 1.1.3">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-1-3.html" title="Index of new symbols in 1.1.3">
+<link rel="next" href="api-index-1-0-5.html" title="Index of new symbols in 1.0.5">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-0-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-1-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-1-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-0-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -33,6 +33,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 6ac7520..cc9d926 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-1-2.html" title="Index of new symbols in 1.1.2">
-<link rel="next" href="api-index-1-2-3.html" title="Index of new symbols in 1.2.3">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-2-3.html" title="Index of new symbols in 1.2.3">
+<link rel="next" href="api-index-1-1-2.html" title="Index of new symbols in 1.1.2">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-1-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-2-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-2-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-1-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-1-1-3"></a>Index of new symbols in 1.1.3</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxF"></a><h3 class="title">F</h3>
@@ -44,6 +44,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 0da0a7b..36bf20c 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-1-3.html" title="Index of new symbols in 1.1.3">
-<link rel="next" href="api-index-1-3-3.html" title="Index of new symbols in 1.3.3">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-3-3.html" title="Index of new symbols in 1.3.3">
+<link rel="next" href="api-index-1-1-3.html" title="Index of new symbols in 1.1.3">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-1-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-3-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-3-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-1-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -41,6 +41,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index c10e208..f5687f5 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-2-3.html" title="Index of new symbols in 1.2.3">
-<link rel="next" href="api-index-1-4-2.html" title="Index of new symbols in 1.4.2">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-4-0.html" title="Index of new symbols in 1.4.0">
+<link rel="next" href="api-index-1-2-3.html" title="Index of new symbols in 1.2.3">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-2-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-4-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-4-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-2-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -81,6 +81,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-4-0.html b/docs/html/api-index-1-4-0.html
new file mode 100644 (file)
index 0000000..c6bfe97
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.4.0: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-4-2.html" title="Index of new symbols in 1.4.2">
+<link rel="next" href="api-index-1-3-3.html" title="Index of new symbols in 1.3.3">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-4-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-3-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-4-0"></a>Index of new symbols in 1.4.0</h2></div></div></div>
+<div xmlns:xlink="http://www.w3.org/1999/xlink" class="index"></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index facfc1e..e7fd690 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-3-3.html" title="Index of new symbols in 1.3.3">
-<link rel="next" href="api-index-1-4-3.html" title="Index of new symbols in 1.4.3">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-4-3.html" title="Index of new symbols in 1.4.3">
+<link rel="next" href="api-index-1-4-0.html" title="Index of new symbols in 1.4.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -20,8 +20,8 @@
                   <a class="shortcut" href="#idxV">V</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-3-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-4-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-4-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-4-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <dd></dd>
 <a name="idxO"></a><h3 class="title">O</h3>
 <dt>
-hb_ot_var_axis_t, struct in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-count" title="hb_ot_var_get_axis_count ()">hb_ot_var_get_axis_count</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_find_axis, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-has-data" title="hb_ot_var_has_data ()">hb_ot_var_has_data</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_get_axes, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-coords" title="hb_ot_var_normalize_coords ()">hb_ot_var_normalize_coords</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_get_axis_count, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-variations" title="hb_ot_var_normalize_variations ()">hb_ot_var_normalize_variations</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_has_data, function in hb-ot-var
-</dt>
-<dd></dd>
-<dt>
-hb_ot_var_normalize_coords, function in hb-ot-var
-</dt>
-<dd></dd>
-<dt>
-hb_ot_var_normalize_variations, function in hb-ot-var
-</dt>
-<dd></dd>
-<dt>
-HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-deprecated.html#HB-OT-VAR-NO-AXIS-INDEX:CAPS" title="HB_OT_VAR_NO_AXIS_INDEX">HB_OT_VAR_NO_AXIS_INDEX</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <a name="idxV"></a><h3 class="title">V</h3>
@@ -91,6 +79,6 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 0cf5823..9b333ed 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-4-2.html" title="Index of new symbols in 1.4.2">
-<link rel="next" href="api-index-1-5-0.html" title="Index of new symbols in 1.5.0">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-5-0.html" title="Index of new symbols in 1.5.0">
+<link rel="next" href="api-index-1-4-2.html" title="Index of new symbols in 1.4.2">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-4-2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-5-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-5-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-4-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -29,6 +29,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 5fb0943..0321f7a 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-4-3.html" title="Index of new symbols in 1.4.3">
-<link rel="next" href="api-index-1-6-0.html" title="Index of new symbols in 1.6.0">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-6-0.html" title="Index of new symbols in 1.6.0">
+<link rel="next" href="api-index-1-4-3.html" title="Index of new symbols in 1.4.3">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a class="shortcut" href="#idxG">G</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-4-3.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-1-6-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-6-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-4-3.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-1-5-0"></a>Index of new symbols in 1.5.0</h2></div></div></div>
 <a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxG"></a><h3 class="title">G</h3>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 585a60a..cf383a5 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-5-0.html" title="Index of new symbols in 1.5.0">
-<link rel="next" href="deprecated-api-index.html" title="Index of deprecated API">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-1-7-5.html" title="Index of new symbols in 1.7.5">
+<link rel="next" href="api-index-1-5-0.html" title="Index of new symbols in 1.5.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,8 +16,8 @@
 <td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-5-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="deprecated-api-index.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-1-7-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-5-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
@@ -33,6 +33,6 @@
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-7-5.html b/docs/html/api-index-1-7-5.html
new file mode 100644 (file)
index 0000000..3863eea
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.7.5: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-7-7.html" title="Index of new symbols in 1.7.7">
+<link rel="next" href="api-index-1-6-0.html" title="Index of new symbols in 1.6.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-7-7.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-6-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-7-5"></a>Index of new symbols in 1.7.5</h2></div></div></div>
+<a name="idx"></a>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-7-7.html b/docs/html/api-index-1-7-7.html
new file mode 100644 (file)
index 0000000..277561c
--- /dev/null
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.7.7: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-8-0.html" title="Index of new symbols in 1.8.0">
+<link rel="next" href="api-index-1-7-5.html" title="Index of new symbols in 1.7.5">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxF">F</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxM">M</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-8-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-7-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-7-7"></a>Index of new symbols in 1.7.7</h2></div></div></div>
+<a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-blob.html#hb-blob-create-from-file" title="hb_blob_create_from_file ()">hb_blob_create_from_file</a>, function in <a class="link" href="harfbuzz-hb-blob.html" title="hb-blob">hb-blob</a>
+</dt>
+<dd></dd>
+<a name="idxF"></a><h3 class="title">F</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-count" title="hb_face_count ()">hb_face_count</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<a name="idxM"></a><h3 class="title">M</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-allocation-successful" title="hb_map_allocation_successful ()">hb_map_allocation_successful</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-clear" title="hb_map_clear ()">hb_map_clear</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-create" title="hb_map_create ()">hb_map_create</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-del" title="hb_map_del ()">hb_map_del</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-destroy" title="hb_map_destroy ()">hb_map_destroy</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get" title="hb_map_get ()">hb_map_get</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-empty" title="hb_map_get_empty ()">hb_map_get_empty</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-population" title="hb_map_get_population ()">hb_map_get_population</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-user-data" title="hb_map_get_user_data ()">hb_map_get_user_data</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-has" title="hb_map_has ()">hb_map_has</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-is-empty" title="hb_map_is_empty ()">hb_map_is_empty</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-reference" title="hb_map_reference ()">hb_map_reference</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set" title="hb_map_set ()">hb_map_set</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set-user-data" title="hb_map_set_user_data ()">hb_map_set_user_data</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-8-0.html b/docs/html/api-index-1-8-0.html
new file mode 100644 (file)
index 0000000..65476d8
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.8.0: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-8-1.html" title="Index of new symbols in 1.8.1">
+<link rel="next" href="api-index-1-7-7.html" title="Index of new symbols in 1.7.7">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxS">S</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-8-1.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-7-7.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-8-0"></a>Index of new symbols in 1.8.0</h2></div></div></div>
+<a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-blob.html#hb-blob-copy-writable-or-fail" title="hb_blob_copy_writable_or_fail ()">hb_blob_copy_writable_or_fail</a>, function in <a class="link" href="harfbuzz-hb-blob.html" title="hb-blob">hb-blob</a>
+</dt>
+<dd></dd>
+<a name="idxS"></a><h3 class="title">S</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-set.html#hb-set-previous" title="hb_set_previous ()">hb_set_previous</a>, function in <a class="link" href="harfbuzz-hb-set.html" title="hb-set">hb-set</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-set.html#hb-set-previous-range" title="hb_set_previous_range ()">hb_set_previous_range</a>, function in <a class="link" href="harfbuzz-hb-set.html" title="hb-set">hb-set</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-8-1.html b/docs/html/api-index-1-8-1.html
new file mode 100644 (file)
index 0000000..2db6d73
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.8.1: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-8-5.html" title="Index of new symbols in 1.8.5">
+<link rel="next" href="api-index-1-8-0.html" title="Index of new symbols in 1.8.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxS">S</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-8-5.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-8-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-8-1"></a>Index of new symbols in 1.8.1</h2></div></div></div>
+<a name="idx"></a><a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-lookups-substitute-closure" title="hb_ot_layout_lookups_substitute_closure ()">hb_ot_layout_lookups_substitute_closure</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<a name="idxS"></a><h3 class="title">S</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-set.html#hb-set-is-subset" title="hb_set_is_subset ()">hb_set_is_subset</a>, function in <a class="link" href="harfbuzz-hb-set.html" title="hb-set">hb-set</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-8-5.html b/docs/html/api-index-1-8-5.html
new file mode 100644 (file)
index 0000000..4c31dfc
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.8.5: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-8-6.html" title="Index of new symbols in 1.8.6">
+<link rel="next" href="api-index-1-8-1.html" title="Index of new symbols in 1.8.1">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxO">O</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-8-6.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-8-1.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-8-5"></a>Index of new symbols in 1.8.5</h2></div></div></div>
+<a name="idx"></a><a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-features" title="hb_ot_layout_collect_features ()">hb_ot_layout_collect_features</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-8-6.html b/docs/html/api-index-1-8-6.html
new file mode 100644 (file)
index 0000000..b930c3f
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.8.6: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-1-9-0.html" title="Index of new symbols in 1.9.0">
+<link rel="next" href="api-index-1-8-5.html" title="Index of new symbols in 1.8.5">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-1-9-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-8-5.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-8-6"></a>Index of new symbols in 1.8.6</h2></div></div></div>
+<a name="idx"></a><a name="idxF"></a><h3 class="title">F</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advances-func" title="hb_font_funcs_set_glyph_h_advances_func ()">hb_font_funcs_set_glyph_h_advances_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advances-func" title="hb_font_funcs_set_glyph_v_advances_func ()">hb_font_funcs_set_glyph_v_advances_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advances-for-direction" title="hb_font_get_glyph_advances_for_direction ()">hb_font_get_glyph_advances_for_direction</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances" title="hb_font_get_glyph_h_advances ()">hb_font_get_glyph_h_advances</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances" title="hb_font_get_glyph_v_advances ()">hb_font_get_glyph_v_advances</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-1-9-0.html b/docs/html/api-index-1-9-0.html
new file mode 100644 (file)
index 0000000..c04ee2e
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 1.9.0: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-2-0-0.html" title="Index of new symbols in 2.0.0">
+<link rel="next" href="api-index-1-8-6.html" title="Index of new symbols in 1.8.6">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxF">F</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxU">U</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-2-0-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-8-6.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-1-9-0"></a>Index of new symbols in 1.9.0</h2></div></div></div>
+<a name="idx"></a><a name="idxF"></a><h3 class="title">F</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-add-table" title="hb_face_builder_add_table ()">hb_face_builder_add_table</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-create" title="hb_face_builder_create ()">hb_face_builder_create</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-unicodes" title="hb_face_collect_unicodes ()">hb_face_collect_unicodes</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-selectors" title="hb_face_collect_variation_selectors ()">hb_face_collect_variation_selectors</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-unicodes" title="hb_face_collect_variation_unicodes ()">hb_face_collect_variation_unicodes</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<a name="idxU"></a><h3 class="title">U</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-unicode.html#HB-UNICODE-MAX:CAPS" title="HB_UNICODE_MAX">HB_UNICODE_MAX</a>, macro in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-2-0-0.html b/docs/html/api-index-2-0-0.html
new file mode 100644 (file)
index 0000000..bf4c644
--- /dev/null
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 2.0.0: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="api-index-2-1-0.html" title="Index of new symbols in 2.1.0">
+<link rel="next" href="api-index-1-9-0.html" title="Index of new symbols in 1.9.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxF">F</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxO">O</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-2-1-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-1-9-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-2-0-0"></a>Index of new symbols in 2.0.0</h2></div></div></div>
+<a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-invisible-glyph" title="hb_buffer_get_invisible_glyph ()">hb_buffer_get_invisible_glyph</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-invisible-glyph" title="hb_buffer_set_invisible_glyph ()">hb_buffer_set_invisible_glyph</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<a name="idxF"></a><h3 class="title">F</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-END:CAPS" title="HB_FEATURE_GLOBAL_END">HB_FEATURE_GLOBAL_END</a>, macro in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-START:CAPS" title="HB_FEATURE_GLOBAL_START">HB_FEATURE_GLOBAL_START</a>, macro in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyphs-func" title="hb_font_funcs_set_nominal_glyphs_func ()">hb_font_funcs_set_nominal_glyphs_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-characters" title="hb_ot_layout_feature_get_characters ()">hb_ot_layout_feature_get_characters</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-name-ids" title="hb_ot_layout_feature_get_name_ids ()">hb_ot_layout_feature_get_name_ids</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-select-language" title="hb_ot_layout_script_select_language ()">hb_ot_layout_script_select_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-select-script" title="hb_ot_layout_table_select_script ()">hb_ot_layout_table_select_script</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-LANGUAGE:CAPS" title="HB_OT_MAX_TAGS_PER_LANGUAGE">HB_OT_MAX_TAGS_PER_LANGUAGE</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-SCRIPT:CAPS" title="HB_OT_MAX_TAGS_PER_SCRIPT">HB_OT_MAX_TAGS_PER_SCRIPT</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t">hb_ot_name_id_t</a>, typedef in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-from-script-and-language" title="hb_ot_tags_from_script_and_language ()">hb_ot_tags_from_script_and_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-to-script-and-language" title="hb_ot_tags_to_script_and_language ()">hb_ot_tags_to_script_and_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/api-index-2-1-0.html b/docs/html/api-index-2-1-0.html
new file mode 100644 (file)
index 0000000..f1e19aa
--- /dev/null
@@ -0,0 +1,121 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of new symbols in 2.1.0: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="deprecated-api-index.html" title="Index of deprecated API">
+<link rel="next" href="api-index-2-0-0.html" title="Index of new symbols in 2.0.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxC">C</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxO">O</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="deprecated-api-index.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-2-0-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-2-1-0"></a>Index of new symbols in 2.1.0</h2></div></div></div>
+<a name="idx"></a><a name="idxC"></a><h3 class="title">C</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-alpha" title="hb_color_get_alpha()">hb_color_get_alpha</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-blue" title="hb_color_get_blue()">hb_color_get_blue</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-green" title="hb_color_get_green()">hb_color_get_green</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-red" title="hb_color_get_red()">hb_color_get_red</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-t" title="hb_color_t">hb_color_t</a>, typedef in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-get-layers" title="hb_ot_color_glyph_get_layers ()">hb_ot_color_glyph_get_layers</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-png" title="hb_ot_color_glyph_reference_png ()">hb_ot_color_glyph_reference_png</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-svg" title="hb_ot_color_glyph_reference_svg ()">hb_ot_color_glyph_reference_svg</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-layers" title="hb_ot_color_has_layers ()">hb_ot_color_has_layers</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-palettes" title="hb_ot_color_has_palettes ()">hb_ot_color_has_palettes</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-png" title="hb_ot_color_has_png ()">hb_ot_color_has_png</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-svg" title="hb_ot_color_has_svg ()">hb_ot_color_has_svg</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-color-get-name-id" title="hb_ot_color_palette_color_get_name_id ()">hb_ot_color_palette_color_get_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" title="enum hb_ot_color_palette_flags_t">hb_ot_color_palette_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-colors" title="hb_ot_color_palette_get_colors ()">hb_ot_color_palette_get_colors</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-count" title="hb_ot_color_palette_get_count ()">hb_ot_color_palette_get_count</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-flags" title="hb_ot_color_palette_get_flags ()">hb_ot_color_palette_get_flags</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-name-id" title="hb_ot_color_palette_get_name_id ()">hb_ot_color_palette_get_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf16" title="hb_ot_name_get_utf16 ()">hb_ot_name_get_utf16</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf32" title="hb_ot_name_get_utf32 ()">hb_ot_name_get_utf32</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf8" title="hb_ot_name_get_utf8 ()">hb_ot_name_get_utf8</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-list-names" title="hb_ot_name_list_names ()">hb_ot_name_list_names</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 591bfe4..5e0cb84 100644 (file)
@@ -6,14 +6,16 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="object-tree.html" title="Object Hierarchy">
-<link rel="next" href="api-index-0-9-2.html" title="Index of new symbols in 0.9.2">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="harfbuzz-hb-uniscribe.html" title="hb-uniscribe">
+<link rel="next" href="deprecated-api-index.html" title="Index of deprecated API">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxB">B</a>
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxA">A</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxB">B</a>
                      <span class="dim">|</span> 
                   <a class="shortcut" href="#idxC">C</a>
                      <span class="dim">|</span> 
                   <a class="shortcut" href="#idxV">V</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="object-tree.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-0-9-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-uniscribe.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="deprecated-api-index.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="api-index-full"></a>API Index</h2></div></div></div>
-<a name="idx"></a><a name="idxB"></a><h3 class="title">B</h3>
+<a name="idx"></a><a name="idxA"></a><h3 class="title">A</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-selector-t" title="enum hb_aat_layout_feature_selector_t">hb_aat_layout_feature_selector_t</a>, enum in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-name-id" title="hb_aat_layout_feature_type_get_name_id ()">hb_aat_layout_feature_type_get_name_id</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-selector-infos" title="hb_aat_layout_feature_type_get_selector_infos ()">hb_aat_layout_feature_type_get_selector_infos</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" title="enum hb_aat_layout_feature_type_t">hb_aat_layout_feature_type_t</a>, enum in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-get-feature-types" title="hb_aat_layout_get_feature_types ()">hb_aat_layout_get_feature_types</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-positioning" title="hb_aat_layout_has_positioning ()">hb_aat_layout_has_positioning</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-substitution" title="hb_aat_layout_has_substitution ()">hb_aat_layout_has_substitution</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-tracking" title="hb_aat_layout_has_tracking ()">hb_aat_layout_has_tracking</a>, function in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-NO-SELECTOR-INDEX:CAPS" title="HB_AAT_LAYOUT_NO_SELECTOR_INDEX">HB_AAT_LAYOUT_NO_SELECTOR_INDEX</a>, macro in <a class="link" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">hb-aat-layout</a>
+</dt>
+<dd></dd>
+<a name="idxB"></a><h3 class="title">B</h3>
 <dt>
 <a class="link" href="harfbuzz-hb-blob.html#hb-blob-copy-writable-or-fail" title="hb_blob_copy_writable_or_fail ()">hb_blob_copy_writable_or_fail</a>, function in <a class="link" href="harfbuzz-hb-blob.html" title="hb-blob">hb-blob</a>
 </dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t">hb_buffer_content_type_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t">hb_buffer_content_type_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t">hb_buffer_diff_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t">hb_buffer_diff_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-invisible-glyph" title="hb_buffer_get_invisible_glyph ()">hb_buffer_get_invisible_glyph</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()">hb_buffer_message_func_t</a>, user_function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()">hb_buffer_message_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a>, macro in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a>, macro in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-invisible-glyph" title="hb_buffer_set_invisible_glyph ()">hb_buffer_set_invisible_glyph</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-t">hb_buffer_t</a>, typedef in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t">hb_buffer_t</a>, typedef in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <a name="idxC"></a><h3 class="title">C</h3>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#HB-COLOR:CAPS" title="HB_COLOR()">HB_COLOR</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-alpha" title="hb_color_get_alpha()">hb_color_get_alpha</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-blue" title="hb_color_get_blue()">hb_color_get_blue</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-green" title="hb_color_get_green()">hb_color_get_green</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-red" title="hb_color_get_red()">hb_color_get_red</a>, macro in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-t" title="hb_color_t">hb_color_t</a>, typedef in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-coretext.html#hb-coretext-face-create" title="hb_coretext_face_create ()">hb_coretext_face_create</a>, function in <a class="link" href="harfbuzz-hb-coretext.html" title="hb-coretext">hb-coretext</a>
 </dt>
 <dd></dd>
 <dd></dd>
 <a name="idxF"></a><h3 class="title">F</h3>
 <dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-add-table" title="hb_face_builder_add_table ()">hb_face_builder_add_table</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-create" title="hb_face_builder_create ()">hb_face_builder_create</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-unicodes" title="hb_face_collect_unicodes ()">hb_face_collect_unicodes</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-selectors" title="hb_face_collect_variation_selectors ()">hb_face_collect_variation_selectors</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-unicodes" title="hb_face_collect_variation_unicodes ()">hb_face_collect_variation_unicodes</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-face.html#hb-face-count" title="hb_face_count ()">hb_face_count</a>, function in <a class="link" href="harfbuzz-hb-face.html" title="hb-face">hb-face</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-END:CAPS" title="HB_FEATURE_GLOBAL_END">HB_FEATURE_GLOBAL_END</a>, macro in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-t-struct" title="hb_feature_t">hb_feature_t</a>, struct in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-START:CAPS" title="HB_FEATURE_GLOBAL_START">HB_FEATURE_GLOBAL_START</a>, macro in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-t-struct" title="hb_feature_t">hb_feature_t</a>, struct in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-func" title="hb_font_funcs_set_glyph_func ()">hb_font_funcs_set_glyph_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advances-func" title="hb_font_funcs_set_glyph_h_advances_func ()">hb_font_funcs_set_glyph_h_advances_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advances-func" title="hb_font_funcs_set_glyph_v_advances_func ()">hb_font_funcs_set_glyph_v_advances_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advance-func" title="hb_font_funcs_set_glyph_v_advance_func ()">hb_font_funcs_set_glyph_v_advance_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyphs-func" title="hb_font_funcs_set_nominal_glyphs_func ()">hb_font_funcs_set_nominal_glyphs_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyph-func" title="hb_font_funcs_set_nominal_glyph_func ()">hb_font_funcs_set_nominal_glyph_func</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advances-for-direction" title="hb_font_get_glyph_advances_for_direction ()">hb_font_get_glyph_advances_for_direction</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advances-func-t" title="hb_font_get_glyph_advances_func_t ()">hb_font_get_glyph_advances_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advance-for-direction" title="hb_font_get_glyph_advance_for_direction ()">hb_font_get_glyph_advance_for_direction</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances" title="hb_font_get_glyph_h_advances ()">hb_font_get_glyph_h_advances</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances-func-t" title="hb_font_get_glyph_h_advances_func_t">hb_font_get_glyph_h_advances_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advance-func-t" title="hb_font_get_glyph_h_advance_func_t">hb_font_get_glyph_h_advance_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t">hb_font_get_glyph_h_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t">hb_font_get_glyph_h_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-func-t" title="hb_font_get_glyph_kerning_func_t ()">hb_font_get_glyph_kerning_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-func-t" title="hb_font_get_glyph_kerning_func_t ()">hb_font_get_glyph_kerning_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances" title="hb_font_get_glyph_v_advances ()">hb_font_get_glyph_v_advances</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances-func-t" title="hb_font_get_glyph_v_advances_func_t">hb_font_get_glyph_v_advances_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advance-func-t" title="hb_font_get_glyph_v_advance_func_t">hb_font_get_glyph_v_advance_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a>, function in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t">hb_font_get_glyph_v_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-font.html" title="hb-font">hb-font</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t">hb_font_get_glyph_v_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a>, enum in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
-</dt>
-<dd></dd>
-<dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t-struct" title="hb_glyph_info_t">hb_glyph_info_t</a>, struct in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t-struct" title="hb_glyph_position_t">hb_glyph_position_t</a>, struct in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct" title="hb_glyph_position_t">hb_glyph_position_t</a>, struct in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-map-get-type" title="hb_gobject_map_get_type ()">hb_gobject_map_get_type</a>, function in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-memory-mode-get-type" title="hb_gobject_memory_mode_get_type ()">hb_gobject_memory_mode_get_type</a>, function in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-ot-color-palette-flags-get-type" title="hb_gobject_ot_color_palette_flags_get_type ()">hb_gobject_ot_color_palette_flags_get_type</a>, function in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-ot-layout-glyph-class-get-type" title="hb_gobject_ot_layout_glyph_class_get_type ()">hb_gobject_ot_layout_glyph_class_get_type</a>, function in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MAP:CAPS" title="HB_GOBJECT_TYPE_MAP">HB_GOBJECT_TYPE_MAP</a>, macro in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MEMORY-MODE:CAPS" title="HB_GOBJECT_TYPE_MEMORY_MODE">HB_GOBJECT_TYPE_MEMORY_MODE</a>, macro in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-COLOR-PALETTE-FLAGS:CAPS" title="HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS">HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS</a>, macro in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-LAYOUT-GLYPH-CLASS:CAPS" title="HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS">HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS</a>, macro in <a class="link" href="harfbuzz-hb-gobject.html" title="hb-gobject">hb-gobject</a>
 </dt>
 <dd></dd>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-graphite2.html#hb-graphite2-font-get-gr-font" title="hb_graphite2_font_get_gr_font ()">hb_graphite2_font_get_gr_font</a>, function in <a class="link" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">hb-graphite2</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-graphite2.html#HB-GRAPHITE2-TAG-SILF:CAPS" title="HB_GRAPHITE2_TAG_SILF">HB_GRAPHITE2_TAG_SILF</a>, macro in <a class="link" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">hb-graphite2</a>
 </dt>
 <dd></dd>
 <dd></dd>
 <a name="idxM"></a><h3 class="title">M</h3>
 <dt>
-hb_map_allocation_successful, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-allocation-successful" title="hb_map_allocation_successful ()">hb_map_allocation_successful</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_clear, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-clear" title="hb_map_clear ()">hb_map_clear</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_create, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-create" title="hb_map_create ()">hb_map_create</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_del, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-del" title="hb_map_del ()">hb_map_del</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_destroy, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-destroy" title="hb_map_destroy ()">hb_map_destroy</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_get, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get" title="hb_map_get ()">hb_map_get</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_get_empty, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-empty" title="hb_map_get_empty ()">hb_map_get_empty</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_get_population, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-population" title="hb_map_get_population ()">hb_map_get_population</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_get_user_data, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-user-data" title="hb_map_get_user_data ()">hb_map_get_user_data</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_has, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-has" title="hb_map_has ()">hb_map_has</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_is_empty, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-is-empty" title="hb_map_is_empty ()">hb_map_is_empty</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_reference, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-reference" title="hb_map_reference ()">hb_map_reference</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_set, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set" title="hb_map_set ()">hb_map_set</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_set_user_data, function in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set-user-data" title="hb_map_set_user_data ()">hb_map_set_user_data</a>, function in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-hb_map_t, typedef in hb-map
+<a class="link" href="harfbuzz-hb-map.html#hb-map-t">hb_map_t</a>, typedef in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
-HB_MAP_VALUE_INVALID, macro in hb-map
+<a class="link" href="harfbuzz-hb-map.html#HB-MAP-VALUE-INVALID:CAPS" title="HB_MAP_VALUE_INVALID">HB_MAP_VALUE_INVALID</a>, macro in <a class="link" href="harfbuzz-hb-map.html" title="hb-map">hb-map</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1348,10 +1487,66 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 <dd></dd>
 <a name="idxO"></a><h3 class="title">O</h3>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-get-layers" title="hb_ot_color_glyph_get_layers ()">hb_ot_color_glyph_get_layers</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-png" title="hb_ot_color_glyph_reference_png ()">hb_ot_color_glyph_reference_png</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-svg" title="hb_ot_color_glyph_reference_svg ()">hb_ot_color_glyph_reference_svg</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-layers" title="hb_ot_color_has_layers ()">hb_ot_color_has_layers</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-palettes" title="hb_ot_color_has_palettes ()">hb_ot_color_has_palettes</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-png" title="hb_ot_color_has_png ()">hb_ot_color_has_png</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-svg" title="hb_ot_color_has_svg ()">hb_ot_color_has_svg</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-color-get-name-id" title="hb_ot_color_palette_color_get_name_id ()">hb_ot_color_palette_color_get_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" title="enum hb_ot_color_palette_flags_t">hb_ot_color_palette_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-colors" title="hb_ot_color_palette_get_colors ()">hb_ot_color_palette_get_colors</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-count" title="hb_ot_color_palette_get_count ()">hb_ot_color_palette_get_count</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-flags" title="hb_ot_color_palette_get_flags ()">hb_ot_color_palette_get_flags</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-name-id" title="hb_ot_color_palette_get_name_id ()">hb_ot_color_palette_get_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">hb-ot-color</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-font.html#hb-ot-font-set-funcs" title="hb_ot_font_set_funcs ()">hb_ot_font_set_funcs</a>, function in <a class="link" href="harfbuzz-hb-ot-font.html" title="hb-ot-font">hb-ot-font</a>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-features" title="hb_ot_layout_collect_features ()">hb_ot_layout_collect_features</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-lookups" title="hb_ot_layout_collect_lookups ()">hb_ot_layout_collect_lookups</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
@@ -1360,10 +1555,18 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-characters" title="hb_ot_layout_feature_get_characters ()">hb_ot_layout_feature_get_characters</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-lookups" title="hb_ot_layout_feature_get_lookups ()">hb_ot_layout_feature_get_lookups</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-name-ids" title="hb_ot_layout_feature_get_name_ids ()">hb_ot_layout_feature_get_name_ids</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-with-variations-get-lookups" title="hb_ot_layout_feature_with_variations_get_lookups ()">hb_ot_layout_feature_with_variations_get_lookups</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
@@ -1456,15 +1659,11 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-find-language" title="hb_ot_layout_script_find_language ()">hb_ot_layout_script_find_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-get-language-tags" title="hb_ot_layout_script_get_language_tags ()">hb_ot_layout_script_get_language_tags</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-choose-script" title="hb_ot_layout_table_choose_script ()">hb_ot_layout_table_choose_script</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-select-language" title="hb_ot_layout_script_select_language ()">hb_ot_layout_script_select_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1472,7 +1671,7 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-find-script" title="hb_ot_layout_table_find_script ()">hb_ot_layout_table_find_script</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-ot-layout-table-find-script" title="hb_ot_layout_table_find_script ()">hb_ot_layout_table_find_script</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1488,6 +1687,10 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-select-script" title="hb_ot_layout_table_select_script ()">hb_ot_layout_table_select_script</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-constant-t" title="enum hb_ot_math_constant_t">hb_ot_math_constant_t</a>, enum in <a class="link" href="harfbuzz-hb-ot-math.html" title="hb-ot-math">hb-ot-math</a>
 </dt>
 <dd></dd>
@@ -1548,6 +1751,34 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-LANGUAGE:CAPS" title="HB_OT_MAX_TAGS_PER_LANGUAGE">HB_OT_MAX_TAGS_PER_LANGUAGE</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-SCRIPT:CAPS" title="HB_OT_MAX_TAGS_PER_SCRIPT">HB_OT_MAX_TAGS_PER_SCRIPT</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf16" title="hb_ot_name_get_utf16 ()">hb_ot_name_get_utf16</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf32" title="hb_ot_name_get_utf32 ()">hb_ot_name_get_utf32</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf8" title="hb_ot_name_get_utf8 ()">hb_ot_name_get_utf8</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t">hb_ot_name_id_t</a>, typedef in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-list-names" title="hb_ot_name_list_names ()">hb_ot_name_list_names</a>, function in <a class="link" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">hb-ot-name</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="harfbuzz-hb-ot-shape.html#hb-ot-shape-glyphs-closure" title="hb_ot_shape_glyphs_closure ()">hb_ot_shape_glyphs_closure</a>, function in <a class="link" href="harfbuzz-hb-ot-shape.html" title="hb-ot-shape">hb-ot-shape</a>
 </dt>
 <dd></dd>
@@ -1556,19 +1787,23 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tags-from-script" title="hb_ot_tags_from_script ()">hb_ot_tags_from_script</a>, function in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-from-script-and-language" title="hb_ot_tags_from_script_and_language ()">hb_ot_tags_from_script_and_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-to-script-and-language" title="hb_ot_tags_to_script_and_language ()">hb_ot_tags_to_script_and_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS" title="HB_OT_TAG_DEFAULT_LANGUAGE">HB_OT_TAG_DEFAULT_LANGUAGE</a>, macro in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-BASE:CAPS" title="HB_OT_TAG_BASE">HB_OT_TAG_BASE</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS" title="HB_OT_TAG_DEFAULT_SCRIPT">HB_OT_TAG_DEFAULT_SCRIPT</a>, macro in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS" title="HB_OT_TAG_DEFAULT_LANGUAGE">HB_OT_TAG_DEFAULT_LANGUAGE</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-from-language" title="hb_ot_tag_from_language ()">hb_ot_tag_from_language</a>, function in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS" title="HB_OT_TAG_DEFAULT_SCRIPT">HB_OT_TAG_DEFAULT_SCRIPT</a>, macro in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1592,63 +1827,79 @@ HB_MAP_VALUE_INVALID, macro in hb-map
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a>, function in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-script" title="hb_ot_tag_to_script ()">hb_ot_tag_to_script</a>, function in <a class="link" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">hb-ot-layout</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-script" title="hb_ot_tag_to_script ()">hb_ot_tag_to_script</a>, function in <a class="link" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">hb-ot-tag</a>
+<a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-ITALIC:CAPS" title="HB_OT_TAG_VAR_AXIS_ITALIC">HB_OT_TAG_VAR_AXIS_ITALIC</a>, macro in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_TAG_VAR_AXIS_ITALIC, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-OPTICAL-SIZE:CAPS" title="HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE">HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE</a>, macro in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-SLANT:CAPS" title="HB_OT_TAG_VAR_AXIS_SLANT">HB_OT_TAG_VAR_AXIS_SLANT</a>, macro in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_TAG_VAR_AXIS_SLANT, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WEIGHT:CAPS" title="HB_OT_TAG_VAR_AXIS_WEIGHT">HB_OT_TAG_VAR_AXIS_WEIGHT</a>, macro in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_TAG_VAR_AXIS_WEIGHT, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WIDTH:CAPS" title="HB_OT_TAG_VAR_AXIS_WIDTH">HB_OT_TAG_VAR_AXIS_WIDTH</a>, macro in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_TAG_VAR_AXIS_WIDTH, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-axis-flags-t" title="enum hb_ot_var_axis_flags_t">hb_ot_var_axis_flags_t</a>, enum in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_axis_t, struct in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-find-axis-info" title="hb_ot_var_find_axis_info ()">hb_ot_var_find_axis_info</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_find_axis, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-count" title="hb_ot_var_get_axis_count ()">hb_ot_var_get_axis_count</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_get_axes, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-infos" title="hb_ot_var_get_axis_infos ()">hb_ot_var_get_axis_infos</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_get_axis_count, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-named-instance-count" title="hb_ot_var_get_named_instance_count ()">hb_ot_var_get_named_instance_count</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_has_data, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-has-data" title="hb_ot_var_has_data ()">hb_ot_var_has_data</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_normalize_coords, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-design-coords" title="hb_ot_var_named_instance_get_design_coords ()">hb_ot_var_named_instance_get_design_coords</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-hb_ot_var_normalize_variations, function in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-postscript-name-id" title="hb_ot_var_named_instance_get_postscript_name_id ()">hb_ot_var_named_instance_get_postscript_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
 </dt>
 <dd></dd>
 <dt>
-HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-subfamily-name-id" title="hb_ot_var_named_instance_get_subfamily_name_id ()">hb_ot_var_named_instance_get_subfamily_name_id</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-coords" title="hb_ot_var_normalize_coords ()">hb_ot_var_normalize_coords</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-variations" title="hb_ot_var_normalize_variations ()">hb_ot_var_normalize_variations</a>, function in <a class="link" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">hb-ot-var</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#HB-OT-VAR-NO-AXIS-INDEX:CAPS" title="HB_OT_VAR_NO_AXIS_INDEX">HB_OT_VAR_NO_AXIS_INDEX</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <a name="idxP"></a><h3 class="title">P</h3>
@@ -1687,19 +1938,19 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS" title="HB_SEGMENT_PROPERTIES_DEFAULT">HB_SEGMENT_PROPERTIES_DEFAULT</a>, macro in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS" title="HB_SEGMENT_PROPERTIES_DEFAULT">HB_SEGMENT_PROPERTIES_DEFAULT</a>, macro in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a>, function in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a>, function in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t-struct" title="hb_segment_properties_t">hb_segment_properties_t</a>, struct in <a class="link" href="harfbuzz-Buffers.html" title="Buffers">Buffers</a>
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct" title="hb_segment_properties_t">hb_segment_properties_t</a>, struct in <a class="link" href="harfbuzz-hb-buffer.html" title="hb-buffer">hb-buffer</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1763,10 +2014,6 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-set-invert" title="hb_set_invert ()">hb_set_invert</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-set.html#hb-set-is-empty" title="hb_set_is_empty ()">hb_set_is_empty</a>, function in <a class="link" href="harfbuzz-hb-set.html" title="hb-set">hb-set</a>
 </dt>
 <dd></dd>
@@ -1827,15 +2074,15 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape" title="hb_shape ()">hb_shape</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()">hb_shape</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a>, function in <a class="link" href="harfbuzz-Shaping.html" title="Shaping">Shaping</a>
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a>, function in <a class="link" href="harfbuzz-hb-shape.html" title="hb-shape">hb-shape</a>
 </dt>
 <dd></dd>
 <dt>
@@ -1941,18 +2188,10 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-decompose-compatibility" title="hb_unicode_decompose_compatibility ()">hb_unicode_decompose_compatibility</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-decompose-func-t" title="hb_unicode_decompose_func_t ()">hb_unicode_decompose_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-eastasian-width" title="hb_unicode_eastasian_width ()">hb_unicode_eastasian_width</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-create" title="hb_unicode_funcs_create ()">hb_unicode_funcs_create</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
@@ -1997,18 +2236,10 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-compatibility-func" title="hb_unicode_funcs_set_decompose_compatibility_func ()">hb_unicode_funcs_set_decompose_compatibility_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-func" title="hb_unicode_funcs_set_decompose_func ()">hb_unicode_funcs_set_decompose_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-eastasian-width-func" title="hb_unicode_funcs_set_eastasian_width_func ()">hb_unicode_funcs_set_eastasian_width_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
-</dt>
-<dd></dd>
-<dt>
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-general-category-func" title="hb_unicode_funcs_set_general_category_func ()">hb_unicode_funcs_set_general_category_func</a>, function in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
 </dt>
 <dd></dd>
@@ -2041,7 +2272,11 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 </dt>
 <dd></dd>
 <dt>
-<a class="link" href="harfbuzz-hb-unicode.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" title="HB_UNICODE_MAX_DECOMPOSITION_LEN">HB_UNICODE_MAX_DECOMPOSITION_LEN</a>, macro in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
+<a class="link" href="harfbuzz-hb-unicode.html#HB-UNICODE-MAX:CAPS" title="HB_UNICODE_MAX">HB_UNICODE_MAX</a>, macro in <a class="link" href="harfbuzz-hb-unicode.html" title="hb-unicode">hb-unicode</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" title="HB_UNICODE_MAX_DECOMPOSITION_LEN">HB_UNICODE_MAX_DECOMPOSITION_LEN</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
@@ -2127,6 +2362,6 @@ HB_OT_VAR_NO_AXIS_INDEX, macro in hb-ot-var
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index c5309a6..d88dc05 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt01.html" title="Part I. User's manual">
-<link rel="prev" href="hello-harfbuzz.html" title="Hello, HarfBuzz">
+<link rel="prev" href="aat-shaping.html" title="AAT shaping">
 <link rel="next" href="adding-text-to-the-buffer.html" title="Adding text to the buffer">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -16,7 +16,7 @@
 <td width="100%" align="left" class="shortcuts"></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="hello-harfbuzz.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="p" href="aat-shaping.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="adding-text-to-the-buffer.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="chapter">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="creating-and-destroying-buffers"></a>Creating and destroying buffers</h2></div></div></div>
 <p>
-      As we saw in our initial example, a buffer is created and
+      As we saw in our <span class="emphasis"><em>Getting Started</em></span> example, a
+      buffer is created and 
       initialized with <code class="literal">hb_buffer_create()</code>. This
       produces a new, empty buffer object, instantiated with some
       default values and ready to accept your Unicode strings.
     </p>
 <p>
-      HarfBuzz manages the memory of objects that it creates (such as
-      buffers), so you don't have to. When you have finished working on
+      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 <code class="literal">hb_buffer_destroy()</code>:
     </p>
 <pre class="programlisting">
@@ -82,6 +83,6 @@ void somefunc(hb_buffer_t *buffer) {
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index ea051f9..6454786 100644 (file)
@@ -2,13 +2,13 @@
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Building: HarfBuzz Manual</title>
+<title>Building HarfBuzz: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="install-harfbuzz.html" title="Install HarfBuzz">
-<link rel="prev" href="install-harfbuzz.html" title="Install HarfBuzz">
-<link rel="next" href="hello-harfbuzz.html" title="Hello, HarfBuzz">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="install-harfbuzz.html" title="Installing HarfBuzz">
+<link rel="prev" href="install-harfbuzz.html" title="Installing HarfBuzz">
+<link rel="next" href="getting-started.html" title="Getting started with HarfBuzz">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="install-harfbuzz.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
 <td><a accesskey="p" href="install-harfbuzz.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="hello-harfbuzz.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="n" href="getting-started.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="building"></a>Building</h2></div></div></div>
+<a name="building"></a>Building HarfBuzz</h2></div></div></div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="building.linux"></a>Building on Linux</h3></div></div></div>
+<p>
+      <span class="emphasis"><em>(1)</em></span> 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.
+    </p>
 <p>
-      On Linux, install the development packages for FreeType, Cairo, and GLib.
-      For example, on Ubuntu / Debian, you would do:
+      For example, on an Ubuntu or Debian system, you would run:
       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo apt-get install</strong></span> <span class="package">gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev</span>
+       <span class="command"><strong>sudo apt install</strong></span> <span class="package">gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev</span>
       </pre>
 <p>
-      whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
+      On Fedora, RHEL, CentOS, or other Red-Hat–based systems, you would run:
+      </p>
+<pre class="programlisting">
+       <span class="command"><strong>sudo yum install</strong></span> <span class="package">gcc gcc-c++ freetype-devel glib2-devel cairo-devel</span>
+      </pre>
+<p>
+
+    </p>
+<p>
+      <span class="emphasis"><em>(2)</em></span> 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.
+    </p>
+<p>
+      <span class="emphasis"><em>(2)(a)</em></span> If you downloaded the HarfBuzz
+      source code in a tarball, you can now extract the source.
+    </p>
+<p>
+      From a shell in the top-level directory of the extracted source
+      code, you can run <span class="command"><strong>./configure</strong></span> followed by
+      <span class="command"><strong>make</strong></span> as with any other standard package.
+    </p>
+<p>
+      This should leave you with a shared
+      library in the <code class="filename">src/</code> directory, and a few
+      utility programs including <span class="command"><strong>hb-view</strong></span> and
+      <span class="command"><strong>hb-shape</strong></span> under the <code class="filename">util/</code>
+      directory.
+    </p>
+<p>
+      <span class="emphasis"><em>(2)(b)</em></span> 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: <span class="package">pkg-config</span> and
+      <a class="ulink" href="http://www.complang.org/ragel/" target="_top">ragel</a>.
+    </p>
+<p>
+      On Ubuntu or Debian, run:
       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo yum install</strong></span> <span class="package">gcc gcc-c++ freetype-devel glib2-devel cairo-devel</span>
+       <span class="command"><strong>sudo apt-get install</strong></span> <span class="package">autoconf automake libtool pkg-config ragel gtk-doc-tools</span>
       </pre>
 <p>
-      or using MacPorts:
+      On Fedora, RHEL, CentOS, run:
       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo port install</strong></span> <span class="package">freetype glib2 cairo</span>
+       <span class="command"><strong>sudo yum install</strong></span> <span class="package">autoconf automake libtool pkgconfig ragel gtk-doc</span>
       </pre>
 <p>
+      
     </p>
 <p>
-      If you are using a tarball, you can now proceed to running
-      <span class="command"><strong>configure</strong></span> and <span class="command"><strong>make</strong></span> as with any
-      other standard package. That should leave you with a shared library in
-      <code class="filename">src/</code>, and a few utility programs including hb-view
-      and hb-shape under <code class="filename">util/</code>.
+      With <span class="package">pkg-config</span> and <span class="package">ragel</span>
+      installed, you can now run <span class="command"><strong>./autogen.sh</strong></span>,
+      followed by <span class="command"><strong>./configure</strong></span> and
+      <span class="command"><strong>make</strong></span> to build HarfBuzz.
     </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="building.windows"></a>Building on Windows</h3></div></div></div>
 <p>
-      If you are bootstrapping from git, you need a few more tools before you
-      can run <code class="filename">autogen.sh</code> for the first time. Namely,
-      pkg-config and <a class="ulink" href="http://www.complang.org/ragel/" target="_top">ragel</a>.
-      Again, on Ubuntu / Debian:
+       On Windows, consider using Microsoft's free <a class="ulink" href="https://github.com/Microsoft/vcpkg" target="_top">vcpkg</a> utility
+       to build HarfBuzz, its dependencies, and other open-source
+       libraries. 
+      </p>
+<p>
+       If you need to build HarfBuzz from source, first put the
+       <span class="package">ragel</span> binary on your
+       <code class="literal">PATH</code>, then follow the appveyor CI cmake
+       <a class="ulink" href="https://github.com/harfbuzz/harfbuzz/blob/master/appveyor.yml" target="_top">build
+       instructions</a>. 
+      </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="building.macos"></a>Building on macOS</h3></div></div></div>
+<p>
+       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.
+      </p>
+<p>
+       <span class="emphasis"><em>(1)</em></span> You must first install the
+       development packages for FreeType, Cairo, and GLib. If you are
+       using MacPorts, you should run:
       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo apt-get install</strong></span> <span class="package">autoconf automake libtool pkg-config ragel gtk-doc-tools</span>
+       <span class="command"><strong>sudo port install</strong></span> <span class="package">freetype glib2 cairo</span>
       </pre>
 <p>
-      and on Fedora, RHEL, CentOS:
       </p>
+<p>
+       If you are using Homebrew, you should run:
+       </p>
+<pre class="programlisting">   
+         <span class="command"><strong>brew install</strong></span> <span class="package">freetype glib cairo</span>
+       </pre>
+<p>
+      </p>
+<p>
+       <span class="emphasis"><em>(2)</em></span> 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.
+      </p>
+<p>
+       <span class="emphasis"><em>(2)(a)</em></span> If you are installing HarfBuzz
+       from a downloaded tarball release, extract the tarball and
+       open a Terminal in the extracted source-code directory. Run:
+       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo yum install</strong></span> <span class="package">autoconf automake libtool pkgconfig ragel gtk-doc</span>
-      </pre>
+         <span class="command"><strong>./configure</strong></span>
+       </pre>
+<p>
+       followed by:
+       </p>
+<pre class="programlisting">   
+         <span class="command"><strong>make</strong></span>
+       </pre>
+<p>
+       to build HarfBuzz.
+      </p>
 <p>
-      or using MacPorts:
+       <span class="emphasis"><em>(2)(b)</em></span> Alternatively, if you are building
+       HarfBuzz from the source in the HarfBuzz git repository, then
+       you must install several built-time dependencies before
+       proceeding.
+      </p>
+<p>If you are
+       using MacPorts, you should run:
       </p>
 <pre class="programlisting">
-<span class="command"><strong>sudo port install</strong></span> <span class="package">autoconf automake libtool pkgconfig ragel gtk-doc</span>
+       <span class="command"><strong>sudo port install</strong></span> <span class="package">autoconf automake libtool pkgconfig ragel gtk-doc</span> 
       </pre>
 <p>
-    </p>
+      to install the build dependencies.
+      </p>
+<p>If you are using Homebrew, you should run:
+       </p>
+<pre class="programlisting">   
+         <span class="command"><strong>brew install</strong></span> <span class="package">autoconf automake libtool pkgconfig ragel gtk-doc</span>
+       </pre>
+<p>
+       Finally, you can run:
+       </p>
+<pre class="programlisting">
+         <span class="command"><strong>./autogen.sh</strong></span>
+       </pre>
+<p>
+      </p>
+<p>
+       <span class="emphasis"><em>(3)</em></span> You can now build HarfBuzz (on either
+       a MacPorts or a Homebrew system) by running:
+       </p>
+<pre class="programlisting">
+         <span class="command"><strong>./configure</strong></span>
+       </pre>
+<p>
+       followed by:
+       </p>
+<pre class="programlisting">
+         <span class="command"><strong>make</strong></span>
+       </pre>
+<p>
+      </p>
+<p>
+       This should leave you with a shared
+       library in the <code class="filename">src/</code> directory, and a few
+       utility programs including <span class="command"><strong>hb-view</strong></span> and
+       <span class="command"><strong>hb-shape</strong></span> under the <code class="filename">util/</code>
+       directory.
+      </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="configuration"></a>Configuration options</h3></div></div></div>
+<p>
+       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.
+      </p>
+<div class="variablelist"><table border="0" class="variablelist">
+<colgroup>
+<col align="left" valign="top">
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-libstdc++</strong></span></span></p></td>
+<td>
+<p>
+             Allow linking with libstdc++. <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             This option enables or disables linking HarfBuzz to the
+             system's libstdc++ library.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-glib</strong></span></span></p></td>
+<td>
+<p>
+            Use <a class="ulink" href="https://developer.gnome.org/glib/" target="_top">GLib</a>. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-gobject</strong></span></span></p></td>
+<td>
+<p>
+             Use <a class="ulink" href="https://developer.gnome.org/gobject/stable/" target="_top">GObject</a>. <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-cairo</strong></span></span></p></td>
+<td>
+<p>
+             Use <a class="ulink" href="https://cairographics.org/" target="_top">Cairo</a>. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+<p>
+             Note: Cairo is used only by the HarfBuzz
+             command-line utilities, and not by the HarfBuzz library.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-fontconfig</strong></span></span></p></td>
+<td>
+<p>
+             Use <a class="ulink" href="https://www.freedesktop.org/wiki/Software/fontconfig/" target="_top">Fontconfig</a>. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             This option enables or disables usage of the Fontconfig
+             library, which provides font-matching functions and
+             provides access to font properties. The default setting
+             is to check for the presence of Fontconfig and, if it is
+             found, build with Fontconfig support.
+           </p>
+<p>
+             Note: Fontconfig is used only by the HarfBuzz
+             command-line utilities, and not by the HarfBuzz library.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-icu</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="http://site.icu-project.org/home" target="_top">ICU</a> library. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             This option enables or disables usage of the
+             <span class="emphasis"><em>International Components for
+             Unicode</em></span> (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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-ucdn</strong></span></span></p></td>
+<td>
+<p>
+             Use HarfBuzz's <a class="ulink" href="https://github.com/harfbuzz/harfbuzz/tree/master/src/hb-ucdn" target="_top">built-in UCDN library</a>. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             The HarfBuzz source tree includes a <span class="emphasis"><em>Unicode
+             Database and Normalization</em></span> (UCDN) library
+             that provides access to basic character properties in
+             the Unicode Character Database (UCD) as well as low-level
+             normalization functions. HarfBuzz can be built without
+             this UCDN support if the usage of a different UCDN
+             library is desired.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-graphite2</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="http://graphite.sil.org/" target="_top">Graphite2</a> library. <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             This option enables or disables usage of the Graphite2
+             library, which provides support for the Graphite shaping
+             model. 
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-freetype</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="https://www.freetype.org/" target="_top">FreeType</a> library. <span class="emphasis"><em>(Default = auto)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-uniscribe</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="https://docs.microsoft.com/en-us/windows/desktop/intl/uniscribe" target="_top">Uniscribe</a>
+             library (experimental). <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-directwrite</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal" target="_top">DirectWrite</a> library (experimental). <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><span class="command"><strong>--with-coretext</strong></span></span></p></td>
+<td>
+<p>
+             Use the <a class="ulink" href="https://developer.apple.com/documentation/coretext" target="_top">CoreText</a> library. <span class="emphasis"><em>(Default = no)</em></span>
+           </p>
+<p>
+             This option enables or disables usage of the CoreText
+             library. CoreText is available on macOS and iOS systems.
+           </p>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/ch01s03.html b/docs/html/ch01s03.html
new file mode 100644 (file)
index 0000000..afce4d1
--- /dev/null
@@ -0,0 +1,108 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>What does HarfBuzz do?: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
+<link rel="prev" href="why-do-i-need-a-shaping-engine.html" title="Why do I need a shaping engine?">
+<link rel="next" href="what-harfbuzz-doesnt-do.html" title="What HarfBuzz doesn't do">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="what-is-harfbuzz.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="why-do-i-need-a-shaping-engine.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="what-harfbuzz-doesnt-do.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id-1.2.2.6"></a>What does HarfBuzz do?</h2></div></div></div>
+<p>
+      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:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>
+         Indic (covering Devanagari, Bengali, Gujarati,
+         Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu, and
+         Sinhala)
+       </p></li>
+<li class="listitem"><p>
+         Arabic (covering Arabic, N'Ko, Syriac, and Mongolian)
+       </p></li>
+<li class="listitem"><p>
+         Thai and Lao
+       </p></li>
+<li class="listitem"><p>
+         Khmer
+       </p></li>
+<li class="listitem"><p>
+         Myanmar
+       </p></li>
+<li class="listitem"><p>
+         Tibetan
+       </p></li>
+<li class="listitem"><p>
+         Hangul
+       </p></li>
+<li class="listitem"><p>
+         Hebrew
+       </p></li>
+<li class="listitem"><p>
+         The Universal Shaping Engine or <span class="emphasis"><em>USE</em></span>
+         (covering complex scripts not covered by the above shaping
+         models)
+       </p></li>
+<li class="listitem"><p>
+         A default shaping model for non-complex scripts
+         (covering Latin, Cyrillic, Greek, Armenian, Georgian, Tifinagh,
+         and many others)
+       </p></li>
+<li class="listitem"><p>
+         Emoji (including emoji modifier sequences, flag sequences,
+         and ZWJ sequences)
+       </p></li>
+</ul></div>
+<p>
+      In addition to OpenType shaping, HarfBuzz supports the latest
+      version of Graphite shaping (the "Graphite 2" model) and AAT
+      shaping.
+    </p>
+<p>
+      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).
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      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 (<code class="literal">CBDT</code>,
+      <code class="literal">sbix</code>, <code class="literal">COLR/CPAL</code>, and
+      <code class="literal">SVG-OT</code>) 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.
+    </p>
+<p>
+      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.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch03s02.html b/docs/html/ch03s02.html
new file mode 100644 (file)
index 0000000..e3f5af9
--- /dev/null
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Terminology: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="getting-started.html" title="Getting started with HarfBuzz">
+<link rel="prev" href="getting-started.html" title="Getting started with HarfBuzz">
+<link rel="next" href="ch03s03.html" title="A simple shaping example">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="getting-started.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="getting-started.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch03s03.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id-1.2.4.3"></a>Terminology</h2></div></div></div>
+<p>
+      
+    </p>
+<div class="variablelist"><table border="0" class="variablelist">
+<colgroup>
+<col align="left" valign="top">
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td><p><span class="term">script</span></p></td>
+<td>
+<p>
+             In text shaping, a <span class="emphasis"><em>script</em></span> is a
+             writing system: a set of symbols, rules, and conventions
+             that is used to represent a language or multiple
+             languages.
+           </p>
+<p>
+             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.
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term">shaper</span></p></td>
+<td><p>
+             In HarfBuzz, a <span class="emphasis"><em>shaper</em></span> 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
+             non-complex scripts. 
+           </p></td>
+</tr>
+<tr>
+<td><p><span class="term">cluster</span></p></td>
+<td>
+<p>
+             In text shaping, a <span class="emphasis"><em>cluster</em></span> 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.
+           </p>
+<p>
+             HarfBuzz provides three cluster
+             <span class="emphasis"><em>levels</em></span> that implement different
+             approaches to the problem of preserving clusters during
+             shaping operations.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term">grapheme</span></p></td>
+<td>
+<p>
+             In linguistics, a <span class="emphasis"><em>grapheme</em></span> 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.
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term">syllable</span></p></td>
+<td>
+<p>
+             In linguistics, a <span class="emphasis"><em>syllable</em></span> 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.
+           </p>
+<p>
+             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.
+           </p>
+<p>
+             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.
+           </p>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch03s03.html b/docs/html/ch03s03.html
new file mode 100644 (file)
index 0000000..1905b84
--- /dev/null
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>A simple shaping example: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="getting-started.html" title="Getting started with HarfBuzz">
+<link rel="prev" href="ch03s02.html" title="Terminology">
+<link rel="next" href="shaping-concepts.html" title="Shaping concepts">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="getting-started.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch03s02.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="shaping-concepts.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id-1.2.4.4"></a>A simple shaping example</h2></div></div></div>
+<p>
+      Below is the simplest HarfBuzz shaping example possible.
+    </p>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>
+          Create a buffer and put your text in it.
+       </p></li></ol></div>
+<pre class="programlisting">
+      #include &lt;hb.h&gt;
+      hb_buffer_t *buf;
+      buf = hb_buffer_create();
+      hb_buffer_add_utf8(buf, text, -1, 0, -1);
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="2"><p>
+          Guess the script, language and direction of the buffer.
+       </p></li></ol></div>
+<pre class="programlisting">
+      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));
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="3"><p>
+          Create a face and a font, using FreeType for now.
+       </p></li></ol></div>
+<pre class="programlisting">
+      #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);
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="4"><p>
+          Shape!
+       </p></li></ol></div>
+<pre class="programlisting">
+      hb_shape(font, buf, NULL, 0);
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="5"><p>
+          Get the glyph and position information.
+       </p></li></ol></div>
+<pre class="programlisting">
+      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);
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="6"><p>
+          Iterate over each glyph.
+       </p></li></ol></div>
+<pre class="programlisting">
+      for (i = 0; i &lt; glyph_count; ++i) {
+      glyphid = glyph_info[i].codepoint;
+      x_offset = glyph_pos[i].x_offset / 64.0;
+      y_offset = glyph_pos[i].y_offset / 64.0;
+      x_advance = glyph_pos[i].x_advance / 64.0;
+      y_advance = glyph_pos[i].y_advance / 64.0;
+      draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
+      cursor_x += x_advance;
+      cursor_y += y_advance;
+      }
+    </pre>
+<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="7"><p>
+          Tidy up.
+       </p></li></ol></div>
+<pre class="programlisting">
+      hb_buffer_destroy(buf);
+      hb_font_destroy(hb_ft_font);
+    </pre>
+<p>
+      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.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch08.html b/docs/html/ch08.html
deleted file mode 100644 (file)
index 2de5896..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>HarfBuzz API: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="pt02.html" title="Part II. Reference manual">
-<link rel="next" href="harfbuzz-hb.html" title="hb">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts"></td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="pt02.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="chapter">
-<div class="titlepage"><div><div><h2 class="title">
-<a name="id-1.3.3"></a>HarfBuzz API</h2></div></div></div>
-<div class="toc"><dl class="toc">
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb.html">hb</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-Buffers.html">Buffers</a></span><span class="refpurpose"> — Input and output buffers</span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-Shaping.html">Shaping</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot.html">hb-ot</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-tag.html">hb-ot-tag</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"></span>
-</dt>
-<dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"></span>
-</dt>
-</dl></div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/ch09.html b/docs/html/ch09.html
new file mode 100644 (file)
index 0000000..1c709c4
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Core API: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="pt02.html" title="Part II. Reference manual">
+<link rel="next" href="harfbuzz-hb-blob.html" title="hb-blob">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="pt02.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-blob.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.3.4"></a>Core API</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"> — Binary data containers</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-buffer.html">hb-buffer</a></span><span class="refpurpose"> — Input and output buffers</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"> — Common data types</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"> — Deprecated API</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"> — Font face objects</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"> — Font objects</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-map.html">hb-map</a></span><span class="refpurpose"> — Object representing integer to integer mapping</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"> — Object representing a set of integers</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"> — Object representing a shaping plan</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape.html">hb-shape</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"> — Unicode character property access</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"> — Information about the version of HarfBuzz in use</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch10.html b/docs/html/ch10.html
new file mode 100644 (file)
index 0000000..a80ab8c
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>OpenType API: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="harfbuzz-hb-version.html" title="hb-version">
+<link rel="next" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-version.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-color.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.3.5"></a>OpenType API</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-color.html">hb-ot-color</a></span><span class="refpurpose"> — OpenType Color Fonts</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"> — OpenType font implementation</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"> — OpenType Layout</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"> — OpenType Math information</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-name.html">hb-ot-name</a></span><span class="refpurpose"> — OpenType font name information</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"> — OpenType shaping support</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-var.html">hb-ot-var</a></span><span class="refpurpose"> — OpenType Font Variations</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch11.html b/docs/html/ch11.html
new file mode 100644 (file)
index 0000000..3c9039c
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Apple Advanced Typography API: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">
+<link rel="next" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-var.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-aat-layout.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.3.6"></a>Apple Advanced Typography API</h2></div></div></div>
+<div class="toc"><dl class="toc"><dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-aat-layout.html">hb-aat-layout</a></span><span class="refpurpose"> — Apple Advanced Typography Layout</span>
+</dt></dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/ch12.html b/docs/html/ch12.html
new file mode 100644 (file)
index 0000000..0c63823
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Integration API: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt02.html" title="Part II. Reference manual">
+<link rel="prev" href="harfbuzz-hb-aat-layout.html" title="hb-aat-layout">
+<link rel="next" href="harfbuzz-hb-coretext.html" title="hb-coretext">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-aat-layout.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-coretext.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.3.7"></a>Integration API</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"> — CoreText integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"> — FreeType integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"> — GLib integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"> — GObject integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"> — Graphite2 integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"> — ICU integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"> — Windows integration</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 2b3078f..9162099 100644 (file)
@@ -2,13 +2,13 @@
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>: HarfBuzz Manual</title>
+<title>Clusters: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt01.html" title="Part I. User's manual">
 <link rel="prev" href="using-your-own-font-functions.html" title="Using your own font functions">
-<link rel="next" href="a-clustering-example-for-levels-0-and-1.html" title="A clustering example for levels 0 and 1">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="working-with-harfbuzz-clusters.html" title="Working with HarfBuzz clusters">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
 <td><a accesskey="p" href="using-your-own-font-functions.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="a-clustering-example-for-levels-0-and-1.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="n" href="working-with-harfbuzz-clusters.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="chapter">
-<div class="titlepage"></div>
+<div class="titlepage"><div><div><h2 class="title">
+<a name="clusters"></a>Clusters</h2></div></div></div>
 <div class="toc"><dl class="toc">
-<dt><span class="sect1"><a href="clusters.html#clusters">Clusters</a></span></dt>
-<dt><span class="sect1"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="level-2.html">Level 2</a></span></dt>
+<dt><span class="section"><a href="clusters.html#clusters-and-shaping">Clusters and shaping</a></span></dt>
+<dt><span class="section"><a href="working-with-harfbuzz-clusters.html">Working with HarfBuzz clusters</a></span></dt>
+<dt><span class="section"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="level-2.html">Level 2</a></span></dt>
 <dd><dl>
-<dt><span class="sect2"><a href="level-2.html#ligatures-with-combining-marks">Ligatures with combining marks</a></span></dt>
-<dt><span class="sect2"><a href="level-2.html#reordering">Reordering</a></span></dt>
+<dt><span class="section"><a href="level-2.html#ligatures-with-combining-marks-in-level-2">Ligatures with combining marks in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#reordering-in-level-2">Reordering in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#other-considerations-in-level-2">Other considerations in level 2</a></span></dt>
 </dl></dd>
 </dl></div>
-<div class="sect1">
+<div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="clusters"></a>Clusters</h2></div></div></div>
+<a name="clusters-and-shaping"></a>Clusters and shaping</h2></div></div></div>
 <p>
-    In shaping text, a <span class="emphasis"><em>cluster</em></span> is a sequence of
-    code points that needs to be treated as a single, indivisible unit.
-  </p>
+      In text shaping, a <span class="emphasis"><em>cluster</em></span> 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 — such as a ligature or conjunct form
+      — and require the shaper to ensure that the cluster is not
+      broken during the shaping process.
+    </p>
 <p>
-    When you add text to a HB buffer, each character is associated with
-    a <span class="emphasis"><em>cluster value</em></span>. This is an arbitrary number as
-    far as HB is concerned.
-  </p>
+      A cluster is distinct from a <span class="emphasis"><em>grapheme</em></span>,
+      which is the smallest unit of meaning in a writing system or
+      script.
+    </p>
 <p>
-    Most clients will use UTF-8, UTF-16, or UTF-32 indices, but the
-    actual number does not matter. Moreover, it is not required for the
-    cluster values to be monotonically increasing, but pretty much all
-    of HB's tests are performed on monotonically increasing cluster
-    numbers. Nevertheless, there is no such assumption in the code
-    itself. With that in mind, let's examine what happens with cluster
-    values during shaping under each cluster-level.
-  </p>
+      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.
+    </p>
 <p>
-    HarfBuzz provides three <span class="emphasis"><em>levels</em></span> of clustering
-    support. Level 0 is the default behavior and reproduces the behavior
-    of the old HarfBuzz library. Level 1 tweaks this behavior slightly
-    to produce better results, so level 1 clustering is recommended for
-    code that is not required to implement backward compatibility with
-    the old HarfBuzz.
-  </p>
+      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 —
+      even though the two original, underlying letters remain separate
+      graphemes.
+    </p>
 <p>
-    Level 2 differs significantly in how it treats cluster values.
-    Levels 0 and 1 both process ligatures and glyph decomposition by
-    merging clusters; level 2 does not.
-  </p>
+      HarfBuzz is concerned with clusters, <span class="emphasis"><em>not</em></span>
+      with graphemes — although client programs using HarfBuzz
+      may still care about graphemes for other reasons from time to time.
+    </p>
 <p>
-    The conceptual model for what the cluster values mean, in levels 0
-    and 1, is this:
-  </p>
-<div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc; ">
+      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
+      <code class="literal">ccmp</code> feature). Operations like these alter
+      clusters; HarfBuzz tracks the changes to ensure that no clusters
+      get lost or broken during shaping. 
+    </p>
+<p>
+      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:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>
+         Correctly positioning the cursor within a shaped text run,
+         even when characters have formed ligatures, composed or
+         decomposed, reordered, or undergone other shaping operations.
+       </p></li>
 <li class="listitem"><p>
-        the sequence of cluster values will always remain monotone
-      </p></li>
+         Correctly highlighting a text selection that includes some,
+         but not all, of the characters in a word. 
+       </p></li>
 <li class="listitem"><p>
-        each value represents a single cluster
-      </p></li>
+         Applying text attributes (such as color or underlining) to
+         part, but not all, of a word.
+       </p></li>
 <li class="listitem"><p>
-        each cluster contains one or more glyphs and one or more
-        characters
-      </p></li>
+         Generating output document formats (such as PDF) with
+         embedded text that can be fully extracted.
+       </p></li>
+<li class="listitem"><p>
+         Determining the mapping between input characters and output
+         glyphs, such as which glyphs are ligatures.
+       </p></li>
+<li class="listitem"><p>
+         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.
+       </p></li>
 </ul></div>
-<p>
-    Assuming that initial cluster numbers were monotonically increasing
-    and distinct, then all adjacent glyphs having the same cluster
-    number belong to the same cluster, and all characters belong to the
-    cluster that has the highest number not larger than their initial
-    cluster number. This will become clearer with an example.
-  </p>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/complex-scripts.html b/docs/html/complex-scripts.html
new file mode 100644 (file)
index 0000000..4ee994b
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Complex scripts: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="next" href="shaping-operations.html" title="Shaping operations">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="shaping-concepts.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="shaping-operations.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="complex-scripts"></a>Complex scripts</h2></div></div></div>
+<p>
+      In text-shaping terminology, scripts are generally classified as
+      either <span class="emphasis"><em>complex</em></span> or <span class="emphasis"><em>non-complex</em></span>.
+    </p>
+<p>
+      Complex scripts are those for which transforming the input
+      sequence into the final layout requires some combination of
+      operations—such as context-dependent substitutions,
+      context-dependent mark positioning, glyph-to-glyph joining,
+      glyph reordering, or glyph stacking.
+    </p>
+<p>
+      In some complex scripts, the shaping rules require that a text
+      run be divided into syllables before the operations can be
+      applied. Other complex scripts may apply shaping operations over
+      entire words or over the entire text run, with no subdivision
+      required.
+    </p>
+<p>
+      Non-complex scripts, by definition, do not require these
+      operations. However, correctly shaping a text run in a
+      non-complex script may still involve Unicode normalization,
+      ligature substitutions, mark positioning, kerning, and applying
+      other font features. The key difference is that a text run in a
+      non-complex script can be processed sequentially and in the same
+      order as the input sequence of Unicode codepoints, without
+      requiring an analysis stage.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 2167383..090b871 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
 <link rel="prev" href="what-about-the-other-scripts.html" title="What about the other scripts?">
 <link rel="next" href="fonts-and-faces.html" title="Fonts and faces">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index fb043a8..5162862 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="api-index-1-6-0.html" title="Index of new symbols in 1.6.0">
-<link rel="next" href="annotation-glossary.html" title="Annotation Glossary">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="api-index-full.html" title="API Index">
+<link rel="next" href="api-index-2-1-0.html" title="Index of new symbols in 2.1.0">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                      <span class="dim">|</span> 
                   <a class="shortcut" href="#idxF">F</a>
                      <span class="dim">|</span> 
-                  <a class="shortcut" href="#idxG">G</a>
+                  <a class="shortcut" href="#idxO">O</a>
                      <span class="dim">|</span> 
-                  <a class="shortcut" href="#idxS">S</a></span></td>
+                  <a class="shortcut" href="#idxS">S</a>
+                     <span class="dim">|</span> 
+                  <a class="shortcut" href="#idxU">U</a></span></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="api-index-1-6-0.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="annotation-glossary.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="p" href="api-index-full.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-2-1-0.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="index">
 <div class="titlepage"><div><div><h2 class="title">
 <dd></dd>
 <a name="idxF"></a><h3 class="title">F</h3>
 <dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-func" title="hb_font_funcs_set_glyph_func ()">hb_font_funcs_set_glyph_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <dt>
 <a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" title="hb_font_get_glyph_func_t ()">hb_font_get_glyph_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
-<a name="idxG"></a><h3 class="title">G</h3>
 <dt>
-<a class="link" href="harfbuzz-hb-graphite2.html#hb-graphite2-font-get-gr-font" title="hb_graphite2_font_get_gr_font ()">hb_graphite2_font_get_gr_font</a>, function in <a class="link" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">hb-graphite2</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t">hb_font_get_glyph_h_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-func-t" title="hb_font_get_glyph_kerning_func_t ()">hb_font_get_glyph_kerning_func_t</a>, user_function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t">hb_font_get_glyph_v_kerning_func_t</a>, typedef in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+</dt>
+<dd></dd>
+<a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="harfbuzz-hb-deprecated.html#HB-OT-VAR-NO-AXIS-INDEX:CAPS" title="HB_OT_VAR_NO_AXIS_INDEX">HB_OT_VAR_NO_AXIS_INDEX</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 <a name="idxS"></a><h3 class="title">S</h3>
 <a class="link" href="harfbuzz-hb-deprecated.html#HB-SCRIPT-CANADIAN-ABORIGINAL:CAPS" title="HB_SCRIPT_CANADIAN_ABORIGINAL">HB_SCRIPT_CANADIAN_ABORIGINAL</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
+<a name="idxU"></a><h3 class="title">U</h3>
 <dt>
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-set-invert" title="hb_set_invert ()">hb_set_invert</a>, function in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
+<a class="link" href="harfbuzz-hb-deprecated.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" title="HB_UNICODE_MAX_DECOMPOSITION_LEN">HB_UNICODE_MAX_DECOMPOSITION_LEN</a>, macro in <a class="link" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">hb-deprecated</a>
 </dt>
 <dd></dd>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index a7abf0e..87dd7a6 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="pt01.html" title="Part I. User's manual">
 <link rel="prev" href="customizing-unicode-functions.html" title="Customizing Unicode functions">
 <link rel="next" href="using-harfbuzzs-native-opentype-implementation.html" title="Using HarfBuzz's native OpenType implementation">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -35,6 +35,6 @@
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/getting-started.html b/docs/html/getting-started.html
new file mode 100644 (file)
index 0000000..3372136
--- /dev/null
@@ -0,0 +1,96 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Getting started with HarfBuzz: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt01.html" title="Part I. User's manual">
+<link rel="prev" href="building.html" title="Building HarfBuzz">
+<link rel="next" href="ch03s02.html" title="Terminology">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="building.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch03s02.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="getting-started"></a>Getting started with HarfBuzz</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt><span class="section"><a href="getting-started.html#id-1.2.4.2">An overview of the HarfBuzz shaping API</a></span></dt>
+<dt><span class="section"><a href="ch03s02.html">Terminology</a></span></dt>
+<dt><span class="section"><a href="ch03s03.html">A simple shaping example</a></span></dt>
+</dl></div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id-1.2.4.2"></a>An overview of the HarfBuzz shaping API</h2></div></div></div>
+<p>
+      The core of the HarfBuzz shaping API is the function
+      <code class="function">hb_shape()</code>. 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.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      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 <code class="literal">Default
+      Ignorable</code> codepoints, and to modify the cluster-merging
+      behavior for the buffer. For shaped output buffers, the
+      individual X and Y offsets and <code class="literal">advances</code>
+      (the logical dimensions) of each glyph are 
+      accessible. HarfBuzz also flags glyphs as
+      <code class="literal">UNSAFE_TO_BREAK</code> if breaking the string at
+      that glyph (e.g., in a line-breaking or hyphenation process)
+      would require re-shaping the text.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      Although the default <code class="function">hb_shape()</code> function is
+      sufficient for most use cases, a variant is also provide that
+      lets you specify which of HarfBuzz's shapers to use on a buffer. 
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      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.
+    </p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/graphite-shaping.html b/docs/html/graphite-shaping.html
new file mode 100644 (file)
index 0000000..5285e3f
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Graphite shaping: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="opentype-shaping-models.html" title="OpenType shaping models">
+<link rel="next" href="aat-shaping.html" title="AAT shaping">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="opentype-shaping-models.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="aat-shaping.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="graphite-shaping"></a>Graphite shaping</h2></div></div></div>
+<p>
+      In contrast to OpenType shaping, Graphite shaping does not
+      specify a predefined set of shaping models or a set of supported
+      scripts.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      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.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-Buffers.html b/docs/html/harfbuzz-Buffers.html
deleted file mode 100644 (file)
index af4e7a3..0000000
+++ /dev/null
@@ -1,2974 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Buffers: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-unicode.html" title="hb-unicode">
-<link rel="next" href="harfbuzz-hb-blob.html" title="hb-blob">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts">
-<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-Buffers.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-Buffers.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
-</td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-unicode.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-blob.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="refentry">
-<a name="harfbuzz-Buffers"></a><div class="titlepage"></div>
-<div class="refnamediv"><table width="100%"><tr>
-<td valign="top">
-<h2><span class="refentrytitle"><a name="harfbuzz-Buffers.top_of_page"></a>Buffers</span></h2>
-<p>Buffers — Input and output buffers</p>
-</td>
-<td class="gallery_image" valign="top" align="right"></td>
-</tr></table></div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.functions"></a><h2>Functions</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="functions_return">
-<col class="functions_name">
-</colgroup>
-<tbody>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="returnvalue">hb_buffer_content_type_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="returnvalue">hb_direction_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="returnvalue">hb_buffer_flags_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="returnvalue">hb_buffer_cluster_level_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="returnvalue">hb_glyph_info_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t"><span class="returnvalue">hb_glyph_position_t</span></a> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="returnvalue">hb_buffer_serialize_format_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">const <span class="returnvalue">char</span> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">const <span class="returnvalue">char</span> **
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t"><span class="returnvalue">hb_buffer_diff_flags_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="returnvalue">hb_glyph_flags_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<span class="c_punctuation">(</span><a class="link" href="harfbuzz-Buffers.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()">*hb_buffer_message_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
-</td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<a name="hb-buffer-t"></a><a name="hb-glyph-info-t"></a><a name="hb-glyph-position-t"></a><a name="hb-segment-properties-t"></a><div class="refsect1">
-<a name="harfbuzz-Buffers.other"></a><h2>Types and Values</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="name">
-<col class="description">
-</colgroup>
-<tbody>
-<tr>
-<td class="define_keyword">#define</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS" title="HB_SEGMENT_PROPERTIES_DEFAULT">HB_SEGMENT_PROPERTIES_DEFAULT</a></td>
-</tr>
-<tr>
-<td class="define_keyword">#define</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a></td>
-</tr>
-<tr>
-<td class="typedef_keyword">typedef</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t">hb_buffer_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword"> </td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t-struct" title="hb_glyph_info_t">hb_glyph_info_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword"> </td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t-struct" title="hb_glyph_position_t">hb_glyph_position_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t">hb_buffer_content_type_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword"> </td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t-struct" title="hb_segment_properties_t">hb_segment_properties_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a></td>
-</tr>
-<tr>
-<td class="datatype_keyword">enum</td>
-<td class="function_name"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t">hb_buffer_diff_flags_t</a></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
-    <span class="lineart">├──</span> hb_buffer_t
-    <span class="lineart">├──</span> hb_glyph_info_t
-    <span class="lineart">├──</span> hb_glyph_position_t
-    <span class="lineart">╰──</span> hb_segment_properties_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
-    <span class="lineart">├──</span> hb_buffer_cluster_level_t
-    <span class="lineart">├──</span> hb_buffer_content_type_t
-    <span class="lineart">╰──</span> hb_buffer_serialize_format_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
-    <span class="lineart">├──</span> hb_buffer_diff_flags_t
-    <span class="lineart">├──</span> hb_buffer_flags_t
-    <span class="lineart">├──</span> hb_buffer_serialize_flags_t
-    <span class="lineart">╰──</span> hb_glyph_flags_t
-</pre>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.includes"></a><h2>Includes</h2>
-<pre class="synopsis">#include &lt;hb.h&gt;
-</pre>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.description"></a><h2>Description</h2>
-<p>Buffers serve dual role in HarfBuzz; they hold the input characters that are
-passed <a class="link" href="harfbuzz-Shaping.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a>, and after shaping they hold the output glyphs.</p>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.functions_details"></a><h2>Functions</h2>
-<div class="refsect2">
-<a name="hb-buffer-create"></a><h3>hb_buffer_create ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-hb_buffer_create (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
-<p>Creates a new <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> with all properties to defaults.</p>
-<p><span class="annotation">[Xconstructor]</span></p>
-<div class="refsect3">
-<a name="hb-buffer-create.returns"></a><h4>Returns</h4>
-<p>A newly allocated <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> with a reference count of 1. The initial
-reference count should be released with <a class="link" href="harfbuzz-Buffers.html#hb-buffer-destroy" title="hb_buffer_destroy ()"><code class="function">hb_buffer_destroy()</code></a> when you are done
-using the <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. This function never returns <code class="literal">NULL</code>. If memory cannot
-be allocated, a special <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> object will be returned on which
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()"><code class="function">hb_buffer_allocation_successful()</code></a> returns <code class="literal">false</code>. </p>
-<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-reference"></a><h3>hb_buffer_reference ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-hb_buffer_reference (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Increases the reference count on <em class="parameter"><code>buffer</code></em>
- by one. This prevents <em class="parameter"><code>buffer</code></em>
- from
-being destroyed until a matching call to <a class="link" href="harfbuzz-Buffers.html#hb-buffer-destroy" title="hb_buffer_destroy ()"><code class="function">hb_buffer_destroy()</code></a> is made.</p>
-<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
-<div class="refsect3">
-<a name="hb-buffer-reference.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-reference.returns"></a><h4>Returns</h4>
-<p>The referenced <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. </p>
-<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-empty"></a><h3>hb_buffer_get_empty ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
-hb_buffer_get_empty (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-get-empty.returns"></a><h4>Returns</h4>
-<p>. </p>
-<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-destroy"></a><h3>hb_buffer_destroy ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_destroy (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Deallocate the <em class="parameter"><code>buffer</code></em>
-.
-Decreases the reference count on <em class="parameter"><code>buffer</code></em>
- by one. If the result is zero, then
-<em class="parameter"><code>buffer</code></em>
- and all associated resources are freed. See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-reference" title="hb_buffer_reference ()"><code class="function">hb_buffer_reference()</code></a>.</p>
-<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
-<div class="refsect3">
-<a name="hb-buffer-destroy.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-reset"></a><h3>hb_buffer_reset ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_reset (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Resets the buffer to its initial status, as if it was just newly created
-with <a class="link" href="harfbuzz-Buffers.html#hb-buffer-create" title="hb_buffer_create ()"><code class="function">hb_buffer_create()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-reset.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-clear-contents"></a><h3>hb_buffer_clear_contents ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_clear_contents (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Similar to <a class="link" href="harfbuzz-Buffers.html#hb-buffer-reset" title="hb_buffer_reset ()"><code class="function">hb_buffer_reset()</code></a>, but does not clear the Unicode functions and
-the replacement code point.</p>
-<div class="refsect3">
-<a name="hb-buffer-clear-contents.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-11.html#api-index-0.9.11">0.9.11</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-pre-allocate"></a><h3>hb_buffer_pre_allocate ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_buffer_pre_allocate (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                        <em class="parameter"><code>unsigned <span class="type">int</span> size</code></em>);</pre>
-<p>Pre allocates memory for <em class="parameter"><code>buffer</code></em>
- to fit at least <em class="parameter"><code>size</code></em>
- number of items.</p>
-<div class="refsect3">
-<a name="hb-buffer-pre-allocate.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>size</p></td>
-<td class="parameter_description"><p>number of items to pre allocate.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-pre-allocate.returns"></a><h4>Returns</h4>
-<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
-memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-allocation-successful"></a><h3>hb_buffer_allocation_successful ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_buffer_allocation_successful (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Check if allocating memory for the buffer succeeded.</p>
-<div class="refsect3">
-<a name="hb-buffer-allocation-successful.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-allocation-successful.returns"></a><h4>Returns</h4>
-<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
-memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add"></a><h3>hb_buffer_add ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-               <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> codepoint</code></em>,
-               <em class="parameter"><code>unsigned <span class="type">int</span> cluster</code></em>);</pre>
-<p>Appends a character with the Unicode value of <em class="parameter"><code>codepoint</code></em>
- to <em class="parameter"><code>buffer</code></em>
-, and
-gives it the initial cluster value of <em class="parameter"><code>cluster</code></em>
-. Clusters can be any thing
-the client wants, they are usually used to refer to the index of the
-character in the input text stream and are output in
-<span class="type">hb_glyph_info_t.cluster</span> field.</p>
-<p>This function does not check the validity of <em class="parameter"><code>codepoint</code></em>
-, it is up to the
-caller to ensure it is a valid Unicode code point.</p>
-<div class="refsect3">
-<a name="hb-buffer-add.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>codepoint</p></td>
-<td class="parameter_description"><p>a Unicode code point.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>cluster</p></td>
-<td class="parameter_description"><p>the cluster value of <em class="parameter"><code>codepoint</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add-codepoints"></a><h3>hb_buffer_add_codepoints ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add_codepoints (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                          <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *text</code></em>,
-                          <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
-                          <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
-                          <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
-<p>Appends characters from <em class="parameter"><code>text</code></em>
- array to <em class="parameter"><code>buffer</code></em>
-. The <em class="parameter"><code>item_offset</code></em>
- is the
-position of the first character from <em class="parameter"><code>text</code></em>
- that will be appended, and
-<em class="parameter"><code>item_length</code></em>
- is the number of character. When shaping part of a larger text
-(e.g. a run of text from a paragraph), instead of passing just the substring
-corresponding to the run, it is preferable to pass the whole
-paragraph and specify the run start and length as <em class="parameter"><code>item_offset</code></em>
- and
-<em class="parameter"><code>item_length</code></em>
-, respectively, to give HarfBuzz the full context to be able,
-for example, to do cross-run Arabic shaping or properly handle combining
-marks at stat of run.</p>
-<p>This function does not check the validity of <em class="parameter"><code>text</code></em>
-, it is up to the caller
-to ensure it contains a valid Unicode code points.</p>
-<div class="refsect3">
-<a name="hb-buffer-add-codepoints.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>a <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to append characters to.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text</p></td>
-<td class="parameter_description"><p>an array of Unicode code points to append. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text_length</p></td>
-<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
-, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_offset</p></td>
-<td class="parameter_description"><p>the offset of the first code point to add to the <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_length</p></td>
-<td class="parameter_description"><p>the number of code points to add to the <em class="parameter"><code>buffer</code></em>
-, or -1 for the
-end of <em class="parameter"><code>text</code></em>
-(assuming it is <code class="literal">NULL</code> terminated).</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add-utf32"></a><h3>hb_buffer_add_utf32 ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add_utf32 (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                     <em class="parameter"><code>const <span class="type">uint32_t</span> *text</code></em>,
-                     <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
-                     <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
-                     <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
-<p>Replaces invalid UTF-32 characters with the <em class="parameter"><code>buffer</code></em>
- replacement code point,
-see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-add-utf32.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text</p></td>
-<td class="parameter_description"><p>an array of UTF-32 characters to append. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text_length</p></td>
-<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
-, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_offset</p></td>
-<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_length</p></td>
-<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
-, or -1 for the
-end of <em class="parameter"><code>text</code></em>
-(assuming it is <code class="literal">NULL</code> terminated).</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add-utf16"></a><h3>hb_buffer_add_utf16 ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add_utf16 (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                     <em class="parameter"><code>const <span class="type">uint16_t</span> *text</code></em>,
-                     <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
-                     <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
-                     <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
-<p>Replaces invalid UTF-16 characters with the <em class="parameter"><code>buffer</code></em>
- replacement code point,
-see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-add-utf16.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text</p></td>
-<td class="parameter_description"><p>an array of UTF-16 characters to append. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text_length</p></td>
-<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
-, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_offset</p></td>
-<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_length</p></td>
-<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
-, or -1 for the
-end of <em class="parameter"><code>text</code></em>
-(assuming it is <code class="literal">NULL</code> terminated).</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add-utf8"></a><h3>hb_buffer_add_utf8 ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add_utf8 (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                    <em class="parameter"><code>const <span class="type">char</span> *text</code></em>,
-                    <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
-                    <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
-                    <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
-<p>Replaces invalid UTF-8 characters with the <em class="parameter"><code>buffer</code></em>
- replacement code point,
-see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-add-utf8.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text</p></td>
-<td class="parameter_description"><p>an array of UTF-8
-characters to append. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text_length</p></td>
-<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
-, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_offset</p></td>
-<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_length</p></td>
-<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
-, or -1 for the
-end of <em class="parameter"><code>text</code></em>
-(assuming it is <code class="literal">NULL</code> terminated).</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-add-latin1"></a><h3>hb_buffer_add_latin1 ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_add_latin1 (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                      <em class="parameter"><code>const <span class="type">uint8_t</span> *text</code></em>,
-                      <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
-                      <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
-                      <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
-<p>Similar to <a class="link" href="harfbuzz-Buffers.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>, but allows only access to first 256
-Unicode code points that can fit in 8-bit strings.</p>
-<div class="note">Has nothing to do with non-Unicode Latin-1 encoding.</div>
-<div class="refsect3">
-<a name="hb-buffer-add-latin1.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text</p></td>
-<td class="parameter_description"><p>an array of UTF-8
-characters to append. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>text_length</p></td>
-<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
-, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_offset</p></td>
-<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>item_length</p></td>
-<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
-, or -1 for the
-end of <em class="parameter"><code>text</code></em>
-(assuming it is <code class="literal">NULL</code> terminated).</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-39.html#api-index-0.9.39">0.9.39</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-append"></a><h3>hb_buffer_append ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_append (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                  <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *source</code></em>,
-                  <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
-                  <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>);</pre>
-<p>Append (part of) contents of another buffer to this buffer.</p>
-<div class="refsect3">
-<a name="hb-buffer-append.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>source</p></td>
-<td class="parameter_description"><p>source <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>start</p></td>
-<td class="parameter_description"><p>start index into source buffer to copy.  Use 0 to copy from start of buffer.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>end</p></td>
-<td class="parameter_description"><p>end index into source buffer to copy.  Use (unsigned int) -1 to copy to end of buffer.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-content-type"></a><h3>hb_buffer_set_content_type ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_content_type (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="type">hb_buffer_content_type_t</span></a> content_type</code></em>);</pre>
-<p>Sets the type of <em class="parameter"><code>buffer</code></em>
- contents, buffers are either empty, contain
-characters (before shaping) or glyphs (the result of shaping).</p>
-<div class="refsect3">
-<a name="hb-buffer-set-content-type.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>content_type</p></td>
-<td class="parameter_description"><p>the type of buffer contents to set</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-content-type"></a><h3>hb_buffer_get_content_type ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="returnvalue">hb_buffer_content_type_t</span></a>
-hb_buffer_get_content_type (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()"><code class="function">hb_buffer_set_content_type()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-content-type.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-content-type.returns"></a><h4>Returns</h4>
-<p>The type of <em class="parameter"><code>buffer</code></em>
-contents.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-direction"></a><h3>hb_buffer_set_direction ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_direction (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> direction</code></em>);</pre>
-<p>Set the text flow direction of the buffer. No shaping can happen without
-setting <em class="parameter"><code>buffer</code></em>
- direction, and it controls the visual direction for the
-output glyphs; for RTL direction the glyphs will be reversed. Many layout
-features depend on the proper setting of the direction, for example,
-reversing RTL text before shaping, then shaping with LTR direction is not
-the same as keeping the text in logical order and shaping with RTL
-direction.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-direction.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>direction</p></td>
-<td class="parameter_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> of the <em class="parameter"><code>buffer</code></em>
-</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-direction"></a><h3>hb_buffer_get_direction ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="returnvalue">hb_direction_t</span></a>
-hb_buffer_get_direction (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a></p>
-<div class="refsect3">
-<a name="hb-buffer-get-direction.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-direction.returns"></a><h4>Returns</h4>
-<p>The direction of the <em class="parameter"><code>buffer</code></em>
-.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-script"></a><h3>hb_buffer_set_script ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_script (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> script</code></em>);</pre>
-<p>Sets the script of <em class="parameter"><code>buffer</code></em>
- to <em class="parameter"><code>script</code></em>
-.</p>
-<p>Script is crucial for choosing the proper shaping behaviour for scripts that
-require it (e.g. Arabic) and the which OpenType features defined in the font
-to be applied.</p>
-<p>You can pass one of the predefined <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> values, or use
-<a class="link" href="harfbuzz-hb-common.html#hb-script-from-string" title="hb_script_from_string ()"><code class="function">hb_script_from_string()</code></a> or <a class="link" href="harfbuzz-hb-common.html#hb-script-from-iso15924-tag" title="hb_script_from_iso15924_tag ()"><code class="function">hb_script_from_iso15924_tag()</code></a> to get the
-corresponding script from an ISO 15924 script tag.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-script.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>script</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> to set.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-script"></a><h3>hb_buffer_get_script ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
-hb_buffer_get_script (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-script.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-script.returns"></a><h4>Returns</h4>
-<p>The <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> of the <em class="parameter"><code>buffer</code></em>
-.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-language"></a><h3>hb_buffer_set_language ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_language (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>);</pre>
-<p>Sets the language of <em class="parameter"><code>buffer</code></em>
- to <em class="parameter"><code>language</code></em>
-.</p>
-<p>Languages are crucial for selecting which OpenType feature to apply to the
-buffer which can result in applying language-specific behaviour. Languages
-are orthogonal to the scripts, and though they are related, they are
-different concepts and should not be confused with each other.</p>
-<p>Use <a class="link" href="harfbuzz-hb-common.html#hb-language-from-string" title="hb_language_from_string ()"><code class="function">hb_language_from_string()</code></a> to convert from ISO 639 language codes to
-<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-language.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>language</p></td>
-<td class="parameter_description"><p>an hb_language_t to set.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-language"></a><h3>hb_buffer_get_language ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
-hb_buffer_get_language (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-language.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-language.returns"></a><h4>Returns</h4>
-<p>The <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> of the buffer. Must not be freed by the caller. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-flags"></a><h3>hb_buffer_set_flags ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_flags (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                     <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="type">hb_buffer_flags_t</span></a> flags</code></em>);</pre>
-<p>Sets <em class="parameter"><code>buffer</code></em>
- flags to <em class="parameter"><code>flags</code></em>
-. See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="type">hb_buffer_flags_t</span></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-flags.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>flags</p></td>
-<td class="parameter_description"><p>the buffer flags to set.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-flags"></a><h3>hb_buffer_get_flags ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="returnvalue">hb_buffer_flags_t</span></a>
-hb_buffer_get_flags (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()"><code class="function">hb_buffer_set_flags()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-flags.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-flags.returns"></a><h4>Returns</h4>
-<p>The <em class="parameter"><code>buffer</code></em>
-flags.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-cluster-level"></a><h3>hb_buffer_set_cluster_level ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_cluster_level (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="type">hb_buffer_cluster_level_t</span></a> cluster_level</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-set-cluster-level.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-42.html#api-index-0.9.42">0.9.42</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-cluster-level"></a><h3>hb_buffer_get_cluster_level ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="returnvalue">hb_buffer_cluster_level_t</span></a>
-hb_buffer_get_cluster_level (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-get-cluster-level.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-42.html#api-index-0.9.42">0.9.42</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-length"></a><h3>hb_buffer_set_length ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_buffer_set_length (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                      <em class="parameter"><code>unsigned <span class="type">int</span> length</code></em>);</pre>
-<p>Similar to <a class="link" href="harfbuzz-Buffers.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()"><code class="function">hb_buffer_pre_allocate()</code></a>, but clears any new items added at the
-end.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-length.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>length</p></td>
-<td class="parameter_description"><p>the new length of <em class="parameter"><code>buffer</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-set-length.returns"></a><h4>Returns</h4>
-<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
-memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-length"></a><h3>hb_buffer_get_length ()</h3>
-<pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_buffer_get_length (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Returns the number of items in the buffer.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-length.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-length.returns"></a><h4>Returns</h4>
-<p>The <em class="parameter"><code>buffer</code></em>
-length.
-The value valid as long as buffer has not been modified.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-segment-properties"></a><h3>hb_buffer_set_segment_properties ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                                  <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>);</pre>
-<p>Sets the segment properties of the buffer, a shortcut for calling
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a>, <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a> and
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a> individually.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-segment-properties.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>props</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to use.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-segment-properties"></a><h3>hb_buffer_get_segment_properties ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_get_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                                  <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>);</pre>
-<p>Sets <em class="parameter"><code>props</code></em>
- to the <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> of <em class="parameter"><code>buffer</code></em>
-.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-segment-properties.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>props</p></td>
-<td class="parameter_description"><p>the output <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-guess-segment-properties"></a><h3>hb_buffer_guess_segment_properties ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_guess_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Sets unset buffer segment properties based on buffer Unicode
-contents.  If buffer is not empty, it must have content type
-<a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"><code class="literal">HB_BUFFER_CONTENT_TYPE_UNICODE</code></a>.</p>
-<p>If buffer script is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-SCRIPT-INVALID:CAPS"><code class="literal">HB_SCRIPT_INVALID</code></a>), it
-will be set to the Unicode script of the first character in
-the buffer that has a script other than <code class="literal">HB_SCRIPT_COMMON</code>,
-<code class="literal">HB_SCRIPT_INHERITED</code>, and <code class="literal">HB_SCRIPT_UNKNOWN</code>.</p>
-<p>Next, if buffer direction is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-INVALID:CAPS"><code class="literal">HB_DIRECTION_INVALID</code></a>),
-it will be set to the natural horizontal direction of the
-buffer script as returned by <a class="link" href="harfbuzz-hb-common.html#hb-script-get-horizontal-direction" title="hb_script_get_horizontal_direction ()"><code class="function">hb_script_get_horizontal_direction()</code></a>.
-If <a class="link" href="harfbuzz-hb-common.html#hb-script-get-horizontal-direction" title="hb_script_get_horizontal_direction ()"><code class="function">hb_script_get_horizontal_direction()</code></a> returns <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-INVALID:CAPS"><code class="literal">HB_DIRECTION_INVALID</code></a>,
-then <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-LTR:CAPS"><code class="literal">HB_DIRECTION_LTR</code></a> is used.</p>
-<p>Finally, if buffer language is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS" title="HB_LANGUAGE_INVALID"><code class="literal">HB_LANGUAGE_INVALID</code></a>),
-it will be set to the process's default language as returned by
-<a class="link" href="harfbuzz-hb-common.html#hb-language-get-default" title="hb_language_get_default ()"><code class="function">hb_language_get_default()</code></a>.  This may change in the future by
-taking buffer script into consideration when choosing a language.</p>
-<div class="refsect3">
-<a name="hb-buffer-guess-segment-properties.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-unicode-funcs"></a><h3>hb_buffer_set_unicode_funcs ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_unicode_funcs (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *unicode_funcs</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-set-unicode-funcs.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-unicode-funcs"></a><h3>hb_buffer_get_unicode_funcs ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
-hb_buffer_get_unicode_funcs (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-get-unicode-funcs.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-user-data"></a><h3>hb_buffer_set_user_data ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_buffer_set_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>,
-                         <em class="parameter"><code><span class="type">void</span> *data</code></em>,
-                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>,
-                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="type">hb_bool_t</span></a> replace</code></em>);</pre>
-<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
-<div class="refsect3">
-<a name="hb-buffer-set-user-data.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-user-data"></a><h3>hb_buffer_get_user_data ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span> *
-hb_buffer_get_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>);</pre>
-<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
-<div class="refsect3">
-<a name="hb-buffer-get-user-data.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-glyph-infos"></a><h3>hb_buffer_get_glyph_infos ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="returnvalue">hb_glyph_info_t</span></a> *
-hb_buffer_get_glyph_infos (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                           <em class="parameter"><code>unsigned <span class="type">int</span> *length</code></em>);</pre>
-<p>Returns <em class="parameter"><code>buffer</code></em>
- glyph information array.  Returned pointer
-is valid as long as <em class="parameter"><code>buffer</code></em>
- contents are not modified.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-glyph-infos.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>length</p></td>
-<td class="parameter_description"><p>output array length. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-glyph-infos.returns"></a><h4>Returns</h4>
-<p>The <em class="parameter"><code>buffer</code></em>
-glyph information array.
-The value valid as long as buffer has not been modified. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=length]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-glyph-positions"></a><h3>hb_buffer_get_glyph_positions ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t"><span class="returnvalue">hb_glyph_position_t</span></a> *
-hb_buffer_get_glyph_positions (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                               <em class="parameter"><code>unsigned <span class="type">int</span> *length</code></em>);</pre>
-<p>Returns <em class="parameter"><code>buffer</code></em>
- glyph position array.  Returned pointer
-is valid as long as <em class="parameter"><code>buffer</code></em>
- contents are not modified.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-glyph-positions.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>length</p></td>
-<td class="parameter_description"><p>output length. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-glyph-positions.returns"></a><h4>Returns</h4>
-<p>The <em class="parameter"><code>buffer</code></em>
-glyph position array.
-The value valid as long as buffer has not been modified. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=length]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-replacement-codepoint"></a><h3>hb_buffer_set_replacement_codepoint ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_replacement_codepoint (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> replacement</code></em>);</pre>
-<p>Sets the <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> that replaces invalid entries for a given encoding
-when adding text to <em class="parameter"><code>buffer</code></em>
-.</p>
-<p>Default is <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT"><code class="literal">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-set-replacement-codepoint.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>replacement</p></td>
-<td class="parameter_description"><p>the replacement <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a></p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-get-replacement-codepoint"></a><h3>hb_buffer_get_replacement_codepoint ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
-hb_buffer_get_replacement_codepoint (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-get-replacement-codepoint.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-get-replacement-codepoint.returns"></a><h4>Returns</h4>
-<p>The <em class="parameter"><code>buffer</code></em>
-replacement <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a>.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-normalize-glyphs"></a><h3>hb_buffer_normalize_glyphs ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_normalize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Reorders a glyph buffer to have canonical in-cluster glyph order / position.
-The resulting clusters should behave identical to pre-reordering clusters.</p>
-<div class="note">This has nothing to do with Unicode normalization.</div>
-<div class="refsect3">
-<a name="hb-buffer-normalize-glyphs.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-reverse"></a><h3>hb_buffer_reverse ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_reverse (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Reverses buffer contents.</p>
-<div class="refsect3">
-<a name="hb-buffer-reverse.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-reverse-range"></a><h3>hb_buffer_reverse_range ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_reverse_range (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                         <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
-                         <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>);</pre>
-<p>Reverses buffer contents between start to end.</p>
-<div class="refsect3">
-<a name="hb-buffer-reverse-range.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>start</p></td>
-<td class="parameter_description"><p>start index.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>end</p></td>
-<td class="parameter_description"><p>end index.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-41.html#api-index-0.9.41">0.9.41</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-reverse-clusters"></a><h3>hb_buffer_reverse_clusters ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_reverse_clusters (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
-<p>Reverses buffer clusters.  That is, the buffer contents are
-reversed, then each cluster (consecutive items having the
-same cluster number) are reversed again.</p>
-<div class="refsect3">
-<a name="hb-buffer-reverse-clusters.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-glyphs"></a><h3>hb_buffer_serialize_glyphs ()</h3>
-<pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_buffer_serialize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                            <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
-                            <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>,
-                            <em class="parameter"><code><span class="type">char</span> *buf</code></em>,
-                            <em class="parameter"><code>unsigned <span class="type">int</span> buf_size</code></em>,
-                            <em class="parameter"><code>unsigned <span class="type">int</span> *buf_consumed</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t"><span class="type">hb_buffer_serialize_flags_t</span></a> flags</code></em>);</pre>
-<p>Serializes <em class="parameter"><code>buffer</code></em>
- into a textual representation of its glyph content,
-useful for showing the contents of the buffer, for example during debugging.
-There are currently two supported serialization formats:</p>
-<div class="refsect3">
-<a name="id-1.3.3.5.12.46.5"></a><h4>text</h4>
-<p>A human-readable, plain text format.
-The serialized glyphs will look something like:</p>
-<p><code class="literal">
-[uni0651=0@518,0+0|uni0628=0+1897]
-</code></p>
-<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
-<li class="listitem"><p>The serialized glyphs are delimited with <code class="literal">[</code> and <code class="literal">]</code>.</p></li>
-<li class="listitem"><p>Glyphs are separated with <code class="literal">|</code></p></li>
-<li class="listitem">
-<p>Each glyph starts with glyph name, or glyph index if
-<a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES</span></a> flag is set. Then,</p>
-<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
-<li class="listitem"><p>If <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS</span></a> is not set, <code class="literal">=</code> then <span class="type">hb_glyph_info_t.cluster</span>.</p></li>
-<li class="listitem">
-<p>If <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS</span></a> is not set, the <a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> in the format:</p>
-<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; ">
-<li class="listitem"><p>If both <span class="type">hb_glyph_position_t.x_offset</span> and <span class="type">hb_glyph_position_t.y_offset</span> are not 0, <code class="literal">@x_offset,y_offset</code>. Then,</p></li>
-<li class="listitem"><p><code class="literal">+x_advance</code>, then <code class="literal">,y_advance</code> if <span class="type">hb_glyph_position_t.y_advance</span> is not 0. Then,</p></li>
-</ul></div>
-</li>
-<li class="listitem"><p>If <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS</span></a> is set, the
-<span class="type">hb_glyph_extents_t</span> in the format
-<code class="literal">&amp;lt;x_bearing,y_bearing,width,height&amp;gt;</code></p></li>
-</ul></div>
-</li>
-</ul></div>
-</div>
-<div class="refsect3">
-<a name="id-1.3.3.5.12.46.6"></a><h4>json</h4>
-<p>TODO.</p>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-serialize-glyphs.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> buffer.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>start</p></td>
-<td class="parameter_description"><p>the first item in <em class="parameter"><code>buffer</code></em>
-to serialize.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>end</p></td>
-<td class="parameter_description"><p>the last item in <em class="parameter"><code>buffer</code></em>
-to serialize.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buf</p></td>
-<td class="parameter_description"><p>output string to
-write serialized buffer into. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_size][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buf_size</p></td>
-<td class="parameter_description"><p>the size of <em class="parameter"><code>buf</code></em>
-.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buf_consumed</p></td>
-<td class="parameter_description"><p>if not <code class="literal">NULL</code>, will be set to the number of byes written into <em class="parameter"><code>buf</code></em>
-. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>font</p></td>
-<td class="parameter_description"><p>the <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> used to shape this buffer, needed to
-read glyph names and extents. If <code class="literal">NULL</code>, and empty font will be used. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>format</p></td>
-<td class="parameter_description"><p>the <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> to use for formatting the output.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>flags</p></td>
-<td class="parameter_description"><p>the <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t"><span class="type">hb_buffer_serialize_flags_t</span></a> that control what glyph properties
-to serialize.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-serialize-glyphs.returns"></a><h4>Returns</h4>
-<p>The number of serialized items.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-deserialize-glyphs"></a><h3>hb_buffer_deserialize_glyphs ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_buffer_deserialize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                              <em class="parameter"><code>const <span class="type">char</span> *buf</code></em>,
-                              <em class="parameter"><code><span class="type">int</span> buf_len</code></em>,
-                              <em class="parameter"><code>const <span class="type">char</span> **end_ptr</code></em>,
-                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                              <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-deserialize-glyphs.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> buffer.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buf</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_len]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>end_ptr</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-format-from-string"></a><h3>hb_buffer_serialize_format_from_string ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="returnvalue">hb_buffer_serialize_format_t</span></a>
-hb_buffer_serialize_format_from_string
-                               (<em class="parameter"><code>const <span class="type">char</span> *str</code></em>,
-                                <em class="parameter"><code><span class="type">int</span> len</code></em>);</pre>
-<p>Parses a string into an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>. Does not check if
-<em class="parameter"><code>str</code></em>
- is a valid buffer serialization format, use
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()"><code class="function">hb_buffer_serialize_list_formats()</code></a> to get the list of supported formats.</p>
-<div class="refsect3">
-<a name="hb-buffer-serialize-format-from-string.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>str</p></td>
-<td class="parameter_description"><p>a string to parse. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>len</p></td>
-<td class="parameter_description"><p>length of <em class="parameter"><code>str</code></em>
-, or -1 if string is <code class="literal">NULL</code> terminated</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-serialize-format-from-string.returns"></a><h4>Returns</h4>
-<p>The parsed <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-format-to-string"></a><h3>hb_buffer_serialize_format_to_string ()</h3>
-<pre class="programlisting">const <span class="returnvalue">char</span> *
-hb_buffer_serialize_format_to_string (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>);</pre>
-<p>Converts <em class="parameter"><code>format</code></em>
- to the string corresponding it, or <code class="literal">NULL</code> if it is not a valid
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-serialize-format-to-string.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>format</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> to convert.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-buffer-serialize-format-to-string.returns"></a><h4>Returns</h4>
-<p>A <code class="literal">NULL</code> terminated string corresponding to <em class="parameter"><code>format</code></em>
-. Should not be freed. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-list-formats"></a><h3>hb_buffer_serialize_list_formats ()</h3>
-<pre class="programlisting">const <span class="returnvalue">char</span> **
-hb_buffer_serialize_list_formats (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
-<p>Returns a list of supported buffer serialization formats.</p>
-<div class="refsect3">
-<a name="hb-buffer-serialize-list-formats.returns"></a><h4>Returns</h4>
-<p>A string array of buffer serialization formats. Should not be freed. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-segment-properties-equal"></a><h3>hb_segment_properties_equal ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_segment_properties_equal (<em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *a</code></em>,
-                             <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *b</code></em>);</pre>
-<p>Checks the equality of two <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a>'s.</p>
-<div class="refsect3">
-<a name="hb-segment-properties-equal.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>a</p></td>
-<td class="parameter_description"><p>first <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to compare.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>b</p></td>
-<td class="parameter_description"><p>second <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to compare.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-segment-properties-equal.returns"></a><h4>Returns</h4>
-<p><code class="literal">true</code> if all properties of <em class="parameter"><code>a</code></em>
-equal those of <em class="parameter"><code>b</code></em>
-, false otherwise.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-segment-properties-hash"></a><h3>hb_segment_properties_hash ()</h3>
-<pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_segment_properties_hash (<em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *p</code></em>);</pre>
-<p>Creates a hash representing <em class="parameter"><code>p</code></em>
-.</p>
-<div class="refsect3">
-<a name="hb-segment-properties-hash.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>p</p></td>
-<td class="parameter_description"><p><a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to hash.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-segment-properties-hash.returns"></a><h4>Returns</h4>
-<p>A hash of <em class="parameter"><code>p</code></em>
-.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-diff"></a><h3>hb_buffer_diff ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t"><span class="returnvalue">hb_buffer_diff_flags_t</span></a>
-hb_buffer_diff (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *reference</code></em>,
-                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> dottedcircle_glyph</code></em>,
-                <em class="parameter"><code>unsigned <span class="type">int</span> position_fuzz</code></em>);</pre>
-<p>If dottedcircle_glyph is (hb_codepoint_t) -1 then <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"><code class="literal">HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT</code></a>
-and <a class="link" href="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"><code class="literal">HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT</code></a> are never returned.  This should be used by most
-callers if just comparing two buffers is needed.</p>
-<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-set-message-func"></a><h3>hb_buffer_set_message_func ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_buffer_set_message_func (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()"><span class="type">hb_buffer_message_func_t</span></a> func</code></em>,
-                            <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-buffer-set-message-func.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>func</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-1-1-3.html#api-index-1.1.3">1.1.3</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-glyph-info-get-glyph-flags"></a><h3>hb_glyph_info_get_glyph_flags ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="returnvalue">hb_glyph_flags_t</span></a>
-hb_glyph_info_get_glyph_flags (<em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a> *info</code></em>);</pre>
-<p>Returns glyph flags encoded within a <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a>.</p>
-<div class="refsect3">
-<a name="hb-glyph-info-get-glyph-flags.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody><tr>
-<td class="parameter_name"><p>info</p></td>
-<td class="parameter_description"><p>a <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a>.</p></td>
-<td class="parameter_annotations"> </td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-glyph-info-get-glyph-flags.returns"></a><h4>Returns</h4>
-<p>The <a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="type">hb_glyph_flags_t</span></a> encoded within <em class="parameter"><code>info</code></em>
-.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-message-func-t"></a><h3>hb_buffer_message_func_t ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-<span class="c_punctuation">(</span>*hb_buffer_message_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                             <em class="parameter"><code>const <span class="type">char</span> *message</code></em>,
-                             <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
-</div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Buffers.other_details"></a><h2>Types and Values</h2>
-<div class="refsect2">
-<a name="HB-SEGMENT-PROPERTIES-DEFAULT:CAPS"></a><h3>HB_SEGMENT_PROPERTIES_DEFAULT</h3>
-<pre class="programlisting">#define             HB_SEGMENT_PROPERTIES_DEFAULT</pre>
-</div>
-<hr>
-<div class="refsect2">
-<a name="HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS"></a><h3>HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</h3>
-<pre class="programlisting">#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
-</pre>
-<p>The default code point for replacing invalid characters in a given encoding.
-Set to U+FFFD REPLACEMENT CHARACTER.</p>
-<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-t"></a><h3>hb_buffer_t</h3>
-<pre class="programlisting">typedef struct hb_buffer_t hb_buffer_t;
-</pre>
-<p>The main structure holding the input text and its properties before shaping,
-and output glyphs and their information after shaping.</p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-glyph-info-t-struct"></a><h3>hb_glyph_info_t</h3>
-<pre class="programlisting">typedef struct {
-  hb_codepoint_t codepoint;
-  hb_mask_t      mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
-  uint32_t       cluster;
-} hb_glyph_info_t;
-</pre>
-<p>The <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a> is the structure that holds information about the
-glyphs and their relation to input text.</p>
-<div class="refsect3">
-<a name="hb-glyph-info-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="struct_members_name">
-<col class="struct_members_description">
-<col width="200px" class="struct_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> <em class="structfield"><code><a name="hb-glyph-info-t-struct.codepoint"></a>codepoint</code></em>;</p></td>
-<td class="struct_member_description"><p>either a Unicode code point (before shaping) or a glyph index
-(after shaping).</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-mask-t" title="hb_mask_t"><span class="type">hb_mask_t</span></a> <em class="structfield"><code><a name="hb-glyph-info-t-struct.mask"></a>mask</code></em>;</p></td>
-<td class="struct_member_description"> </td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><span class="type">uint32_t</span> <em class="structfield"><code><a name="hb-glyph-info-t-struct.cluster"></a>cluster</code></em>;</p></td>
-<td class="struct_member_description"><p>the index of the character in the original text that corresponds
-to this <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a>, or whatever the client passes to
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-add" title="hb_buffer_add ()"><code class="function">hb_buffer_add()</code></a>. More than one <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a> can have the same
-<em class="parameter"><code>cluster</code></em>
-value, if they resulted from the same character (e.g. one
-to many glyph substitution), and when more than one character gets
-merged in the same glyph (e.g. many to one glyph substitution) the
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t"><span class="type">hb_glyph_info_t</span></a> will have the smallest cluster value of them.
-By default some characters are merged into the same cluster
-(e.g. combining marks have the same cluster as their bases)
-even if they are separate glyphs, <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()"><code class="function">hb_buffer_set_cluster_level()</code></a>
-allow selecting more fine-grained cluster handling.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-glyph-flags-t"></a><h3>enum hb_glyph_flags_t</h3>
-<div class="refsect3">
-<a name="hb-glyph-flags-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-GLYPH-FLAG-UNSAFE-TO-BREAK:CAPS"></a>HB_GLYPH_FLAG_UNSAFE_TO_BREAK</p></td>
-<td class="enum_member_description">
-<p>Indicates that if input text is broken at the
-                                  beginning of the cluster this glyph is part of,
-                                  then both sides need to be re-shaped, as the
-                                  result might be different.  On the flip side,
-                                  it means that when this flag is not present,
-                                  then it's safe to break the glyph-run at the
-                                  beginning of this cluster, and the two sides
-                                  represent the exact same result one would get
-                                  if breaking input text at the beginning of
-                                  this cluster and shaping the two sides
-                                  separately.  This can be used to optimize
-                                  paragraph layout, by avoiding re-shaping
-                                  of each line after line-breaking, or limiting
-                                  the reshaping to a small piece around the
-                                  breaking point only.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-GLYPH-FLAG-DEFINED:CAPS"></a>HB_GLYPH_FLAG_DEFINED</p></td>
-<td> </td>
-<td> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-glyph-position-t-struct"></a><h3>hb_glyph_position_t</h3>
-<pre class="programlisting">typedef struct {
-  hb_position_t  x_advance;
-  hb_position_t  y_advance;
-  hb_position_t  x_offset;
-  hb_position_t  y_offset;
-} hb_glyph_position_t;
-</pre>
-<p>The <a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> is the structure that holds the positions of the
-glyph in both horizontal and vertical directions. All positions in
-<a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> are relative to the current point.</p>
-<div class="refsect3">
-<a name="hb-glyph-position-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="struct_members_name">
-<col class="struct_members_description">
-<col width="200px" class="struct_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.x-advance"></a>x_advance</code></em>;</p></td>
-<td class="struct_member_description"><p>how much the line advances after drawing this glyph when setting
-text in horizontal direction.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.y-advance"></a>y_advance</code></em>;</p></td>
-<td class="struct_member_description"><p>how much the line advances after drawing this glyph when setting
-text in vertical direction.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.x-offset"></a>x_offset</code></em>;</p></td>
-<td class="struct_member_description"><p>how much the glyph moves on the X-axis before drawing it, this
-should not affect how much the line advances.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.y-offset"></a>y_offset</code></em>;</p></td>
-<td class="struct_member_description"><p>how much the glyph moves on the Y-axis before drawing it, this
-should not affect how much the line advances.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-content-type-t"></a><h3>enum hb_buffer_content_type_t</h3>
-<div class="refsect3">
-<a name="hb-buffer-content-type-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-INVALID:CAPS"></a>HB_BUFFER_CONTENT_TYPE_INVALID</p></td>
-<td class="enum_member_description">
-<p>Initial value for new buffer.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"></a>HB_BUFFER_CONTENT_TYPE_UNICODE</p></td>
-<td class="enum_member_description">
-<p>The buffer contains input characters (before shaping).</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-GLYPHS:CAPS"></a>HB_BUFFER_CONTENT_TYPE_GLYPHS</p></td>
-<td class="enum_member_description">
-<p>The buffer contains output glyphs (after shaping).</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-flags-t"></a><h3>enum hb_buffer_flags_t</h3>
-<div class="refsect3">
-<a name="hb-buffer-flags-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-DEFAULT:CAPS"></a>HB_BUFFER_FLAG_DEFAULT</p></td>
-<td class="enum_member_description">
-<p>the default buffer flag.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-BOT:CAPS"></a>HB_BUFFER_FLAG_BOT</p></td>
-<td class="enum_member_description">
-<p>flag indicating that special handling of the beginning
-                     of text paragraph can be applied to this buffer. Should usually
-                     be set, unless you are passing to the buffer only part
-                     of the text without the full context.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-EOT:CAPS"></a>HB_BUFFER_FLAG_EOT</p></td>
-<td class="enum_member_description">
-<p>flag indicating that special handling of the end of text
-                     paragraph can be applied to this buffer, similar to
-                     <em class="parameter"><code>HB_BUFFER_FLAG_BOT</code></em>
-.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-PRESERVE-DEFAULT-IGNORABLES:CAPS"></a>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</p></td>
-<td class="enum_member_description">
-<p>                     flag indication that character with Default_Ignorable
-                     Unicode property should use the corresponding glyph
-                     from the font, instead of hiding them (done by
-                     replacing them with the space glyph and zeroing the
-                     advance width.)  This flag takes precedence over
-                     <em class="parameter"><code>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</code></em>
-.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-REMOVE-DEFAULT-IGNORABLES:CAPS"></a>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</p></td>
-<td class="enum_member_description">
-<p>                     flag indication that character with Default_Ignorable
-                     Unicode property should be removed from glyph string
-                     instead of hiding them (done by replacing them with the
-                     space glyph and zeroing the advance width.)
-                     <em class="parameter"><code>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</code></em>
- takes
-                     precedence over this flag. Since: 1.8.0</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-20.html#api-index-0.9.20">0.9.20</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-cluster-level-t"></a><h3>enum hb_buffer_cluster_level_t</h3>
-<div class="refsect3">
-<a name="hb-buffer-cluster-level-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-MONOTONE-GRAPHEMES:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-MONOTONE-CHARACTERS:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-CHARACTERS:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_CHARACTERS</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-DEFAULT:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_DEFAULT</p></td>
-<td> </td>
-<td> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-segment-properties-t-struct"></a><h3>hb_segment_properties_t</h3>
-<pre class="programlisting">typedef struct {
-  hb_direction_t  direction;
-  hb_script_t     script;
-  hb_language_t   language;
-} hb_segment_properties_t;
-</pre>
-<p>The structure that holds various text properties of an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. Can be
-set and retrieved using <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()"><code class="function">hb_buffer_set_segment_properties()</code></a> and
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()"><code class="function">hb_buffer_get_segment_properties()</code></a>, respectively.</p>
-<div class="refsect3">
-<a name="hb-segment-properties-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="struct_members_name">
-<col class="struct_members_description">
-<col width="200px" class="struct_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.direction"></a>direction</code></em>;</p></td>
-<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> of the buffer, see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a>.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.script"></a>script</code></em>;</p></td>
-<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> of the buffer, see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a>.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-<tr>
-<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.language"></a>language</code></em>;</p></td>
-<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> of the buffer, see <a class="link" href="harfbuzz-Buffers.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a>.</p></td>
-<td class="struct_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-format-t"></a><h3>enum hb_buffer_serialize_format_t</h3>
-<p>The buffer serialization and de-serialization format used in
-<a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()"><code class="function">hb_buffer_serialize_glyphs()</code></a> and <a class="link" href="harfbuzz-Buffers.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()"><code class="function">hb_buffer_deserialize_glyphs()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-serialize-format-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-TEXT:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_TEXT</p></td>
-<td class="enum_member_description">
-<p>a human-readable, plain text format.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-JSON:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_JSON</p></td>
-<td class="enum_member_description">
-<p>a machine-readable JSON format.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-INVALID:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_INVALID</p></td>
-<td class="enum_member_description">
-<p>invalid format.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-serialize-flags-t"></a><h3>enum hb_buffer_serialize_flags_t</h3>
-<p>Flags that control what glyph information are serialized in <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()"><code class="function">hb_buffer_serialize_glyphs()</code></a>.</p>
-<div class="refsect3">
-<a name="hb-buffer-serialize-flags-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-DEFAULT:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_DEFAULT</p></td>
-<td class="enum_member_description">
-<p>serialize glyph names, clusters and positions.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS</p></td>
-<td class="enum_member_description">
-<p>do not serialize glyph cluster.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS</p></td>
-<td class="enum_member_description">
-<p>do not serialize glyph position information.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES</p></td>
-<td class="enum_member_description">
-<p>do no serialize glyph name.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS</p></td>
-<td class="enum_member_description">
-<p>serialize glyph extents.</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-GLYPH-FLAGS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS</p></td>
-<td class="enum_member_description">
-<p>serialize glyph flags. Since: 1.5.0</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-ADVANCES:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES</p></td>
-<td class="enum_member_description">
-<p>do not serialize glyph advances,
- glyph offsets will reflect absolute glyph positions. Since: 1.8.0</p>
-</td>
-<td class="enum_member_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-20.html#api-index-0.9.20">0.9.20</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-buffer-diff-flags-t"></a><h3>enum hb_buffer_diff_flags_t</h3>
-<div class="refsect3">
-<a name="hb-buffer-diff-flags-t.members"></a><h4>Members</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="300px" class="enum_members_name">
-<col class="enum_members_description">
-<col width="200px" class="enum_members_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-EQUAL:CAPS"></a>HB_BUFFER_DIFF_FLAG_EQUAL</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CONTENT-TYPE-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-LENGTH-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"></a>HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"></a>HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CODEPOINT-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CLUSTER-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-GLYPH-FLAGS-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-<tr>
-<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-POSITION-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH</p></td>
-<td> </td>
-<td> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-</div>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-Shaping.html b/docs/html/harfbuzz-Shaping.html
deleted file mode 100644 (file)
index a50c761..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Shaping: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-font.html" title="hb-font">
-<link rel="next" href="harfbuzz-hb-version.html" title="hb-version">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts">
-<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-Shaping.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-Shaping.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
-</td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-font.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-version.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="refentry">
-<a name="harfbuzz-Shaping"></a><div class="titlepage"></div>
-<div class="refnamediv"><table width="100%"><tr>
-<td valign="top">
-<h2><span class="refentrytitle"><a name="harfbuzz-Shaping.top_of_page"></a>Shaping</span></h2>
-<p>Shaping — Conversion of text strings into positioned glyphs</p>
-</td>
-<td class="gallery_image" valign="top" align="right"></td>
-</tr></table></div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.functions"></a><h2>Functions</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="functions_return">
-<col class="functions_name">
-</colgroup>
-<tbody>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Shaping.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Shaping.html#hb-shape" title="hb_shape ()">hb_shape</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">const <span class="returnvalue">char</span> **
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-Shaping.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<a name="hb-feature-t"></a><div class="refsect1">
-<a name="harfbuzz-Shaping.other"></a><h2>Types and Values</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="name">
-<col class="description">
-</colgroup>
-<tbody><tr>
-<td class="datatype_keyword"> </td>
-<td class="function_name"><a class="link" href="harfbuzz-Shaping.html#hb-feature-t-struct" title="hb_feature_t">hb_feature_t</a></td>
-</tr></tbody>
-</table></div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
-    <span class="lineart">╰──</span> hb_feature_t
-</pre>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.includes"></a><h2>Includes</h2>
-<pre class="synopsis">#include &lt;hb.h&gt;
-</pre>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.description"></a><h2>Description</h2>
-<p>Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
-which are sequences of Unicode characters that use the same font and have
-the same text direction, script and language. After shaping the buffer
-contains the output glyphs and their positions.</p>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.functions_details"></a><h2>Functions</h2>
-<div class="refsect2">
-<a name="hb-feature-from-string"></a><h3>hb_feature_from_string ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_feature_from_string (<em class="parameter"><code>const <span class="type">char</span> *str</code></em>,
-                        <em class="parameter"><code><span class="type">int</span> len</code></em>,
-                        <em class="parameter"><code><a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *feature</code></em>);</pre>
-<p>Parses a string into a <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a>.</p>
-<p>TODO: document the syntax here.</p>
-<div class="refsect3">
-<a name="hb-feature-from-string.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>str</p></td>
-<td class="parameter_description"><p>a string to parse. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>len</p></td>
-<td class="parameter_description"><p>length of <em class="parameter"><code>str</code></em>
-, or -1 if string is <code class="literal">NULL</code> terminated</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>feature</p></td>
-<td class="parameter_description"><p>the <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> to initialize with the parsed values. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-feature-from-string.returns"></a><h4>Returns</h4>
-<p><code class="literal">true</code> if <em class="parameter"><code>str</code></em>
-is successfully parsed, <code class="literal">false</code> otherwise.</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-feature-to-string"></a><h3>hb_feature_to_string ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_feature_to_string (<em class="parameter"><code><a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *feature</code></em>,
-                      <em class="parameter"><code><span class="type">char</span> *buf</code></em>,
-                      <em class="parameter"><code>unsigned <span class="type">int</span> size</code></em>);</pre>
-<p>Converts a <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> into a <code class="literal">NULL</code>-terminated string in the format
-understood by <a class="link" href="harfbuzz-Shaping.html#hb-feature-from-string" title="hb_feature_from_string ()"><code class="function">hb_feature_from_string()</code></a>. The client in responsible for
-allocating big enough size for <em class="parameter"><code>buf</code></em>
-, 128 bytes is more than enough.</p>
-<div class="refsect3">
-<a name="hb-feature-to-string.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>feature</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> to convert</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buf</p></td>
-<td class="parameter_description"><p>output string. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=size][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>size</p></td>
-<td class="parameter_description"><p>the allocated size of <em class="parameter"><code>buf</code></em>
-</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-shape"></a><h3>hb_shape ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_shape (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-          <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-          <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
-          <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>);</pre>
-<p>Shapes <em class="parameter"><code>buffer</code></em>
- using <em class="parameter"><code>font</code></em>
- turning its Unicode characters content to
-positioned glyphs. If <em class="parameter"><code>features</code></em>
- is not <code class="literal">NULL</code>, it will be used to control the
-features applied during shaping.</p>
-<div class="refsect3">
-<a name="hb-shape.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>font</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> to use for shaping</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to shape</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>features</p></td>
-<td class="parameter_description"><p>an array of user
-specified <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> or <code class="literal">NULL</code>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=num_features][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>num_features</p></td>
-<td class="parameter_description"><p>the length of <em class="parameter"><code>features</code></em>
-array</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-shape-full"></a><h3>hb_shape_full ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_shape_full (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-               <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-               <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
-               <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>,
-               <em class="parameter"><code>const <span class="type">char</span> * const *shaper_list</code></em>);</pre>
-<p>See <a class="link" href="harfbuzz-Shaping.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a> for details. If <em class="parameter"><code>shaper_list</code></em>
- is not <code class="literal">NULL</code>, the specified
-shapers will be used in the given order, otherwise the default shapers list
-will be used.</p>
-<div class="refsect3">
-<a name="hb-shape-full.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>font</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> to use for shaping</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>buffer</p></td>
-<td class="parameter_description"><p>an <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to shape</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>features</p></td>
-<td class="parameter_description"><p>an array of user
-specified <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> or <code class="literal">NULL</code>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=num_features][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>num_features</p></td>
-<td class="parameter_description"><p>the length of <em class="parameter"><code>features</code></em>
-array</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>shaper_list</p></td>
-<td class="parameter_description"><p>a <code class="literal">NULL</code>-terminated
-array of shapers to use or <code class="literal">NULL</code>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> zero-terminated=1][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect3">
-<a name="hb-shape-full.returns"></a><h4>Returns</h4>
-<p> false if all shapers failed, true otherwise</p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-shape-list-shapers"></a><h3>hb_shape_list_shapers ()</h3>
-<pre class="programlisting">const <span class="returnvalue">char</span> **
-hb_shape_list_shapers (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
-<p>Retrieves the list of shapers supported by HarfBuzz.</p>
-<div class="refsect3">
-<a name="hb-shape-list-shapers.returns"></a><h4>Returns</h4>
-<p>an array of
-constant strings. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> zero-terminated=1]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-Shaping.other_details"></a><h2>Types and Values</h2>
-<div class="refsect2">
-<a name="hb-feature-t-struct"></a><h3>hb_feature_t</h3>
-<pre class="programlisting">typedef struct {
-  hb_tag_t      tag;
-  uint32_t      value;
-  unsigned int  start;
-  unsigned int  end;
-} hb_feature_t;
-</pre>
-</div>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-aat-layout.html b/docs/html/harfbuzz-hb-aat-layout.html
new file mode 100644 (file)
index 0000000..01fbdfa
--- /dev/null
@@ -0,0 +1,1755 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-aat-layout: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch11.html" title="Apple Advanced Typography API">
+<link rel="prev" href="ch11.html" title="Apple Advanced Typography API">
+<link rel="next" href="ch12.html" title="Integration API">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-aat-layout.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-aat-layout.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch11.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch11.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch12.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-aat-layout"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-aat-layout.top_of_page"></a>hb-aat-layout</span></h2>
+<p>hb-aat-layout — Apple Advanced Typography Layout</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-name-id" title="hb_aat_layout_feature_type_get_name_id ()">hb_aat_layout_feature_type_get_name_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-selector-infos" title="hb_aat_layout_feature_type_get_selector_infos ()">hb_aat_layout_feature_type_get_selector_infos</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-get-feature-types" title="hb_aat_layout_get_feature_types ()">hb_aat_layout_get_feature_types</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-positioning" title="hb_aat_layout_has_positioning ()">hb_aat_layout_has_positioning</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-substitution" title="hb_aat_layout_has_substitution ()">hb_aat_layout_has_substitution</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-tracking" title="hb_aat_layout_has_tracking ()">hb_aat_layout_has_tracking</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-NO-SELECTOR-INDEX:CAPS" title="HB_AAT_LAYOUT_NO_SELECTOR_INDEX">HB_AAT_LAYOUT_NO_SELECTOR_INDEX</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" title="enum hb_aat_layout_feature_type_t">hb_aat_layout_feature_type_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-selector-t" title="enum hb_aat_layout_feature_selector_t">hb_aat_layout_feature_selector_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <span class="lineart">├──</span> hb_aat_layout_feature_selector_t
+    <span class="lineart">╰──</span> hb_aat_layout_feature_type_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-aat.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.description"></a><h2>Description</h2>
+<p>Functions for querying OpenType Layout features in the font face.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-aat-layout-feature-type-get-name-id"></a><h3>hb_aat_layout_feature_type_get_name_id ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+hb_aat_layout_feature_type_get_name_id
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" title="enum hb_aat_layout_feature_type_t"><span class="type">hb_aat_layout_feature_type_t</span></a> feature_type</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-aat-layout-feature-type-get-name-id.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a face object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>feature_type</p></td>
+<td class="parameter_description"><p>feature id</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-aat-layout-feature-type-get-name-id.returns"></a><h4>Returns</h4>
+<p> Name ID index</p>
+</div>
+<p class="since">Since: 2.2.0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-feature-type-get-selector-infos"></a><h3>hb_aat_layout_feature_type_get_selector_infos ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_aat_layout_feature_type_get_selector_infos
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" title="enum hb_aat_layout_feature_type_t"><span class="type">hb_aat_layout_feature_type_t</span></a> feature_type</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> *selector_count</code></em>,
+                                <em class="parameter"><code><span class="type">hb_aat_layout_feature_selector_info_t</span> *selectors</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> *default_index</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-get-feature-types"></a><h3>hb_aat_layout_get_feature_types ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_aat_layout_get_feature_types (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                 <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                                 <em class="parameter"><code>unsigned <span class="type">int</span> *feature_count</code></em>,
+                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" title="enum hb_aat_layout_feature_type_t"><span class="type">hb_aat_layout_feature_type_t</span></a> *features</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-aat-layout-get-feature-types.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a face object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start_offset</p></td>
+<td class="parameter_description"><p>iteration's start offset</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>feature_count</p></td>
+<td class="parameter_description"><p> buffer size as input, filled size as output. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>features</p></td>
+<td class="parameter_description"><p> features buffer. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=feature_count]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-aat-layout-get-feature-types.returns"></a><h4>Returns</h4>
+<p> Number of all available feature types.</p>
+</div>
+<p class="since">Since: 2.2.0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-has-positioning"></a><h3>hb_aat_layout_has_positioning ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_aat_layout_has_positioning (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-has-substitution"></a><h3>hb_aat_layout_has_substitution ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_aat_layout_has_substitution (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-has-tracking"></a><h3>hb_aat_layout_has_tracking ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_aat_layout_has_tracking (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-aat-layout.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="HB-AAT-LAYOUT-NO-SELECTOR-INDEX:CAPS"></a><h3>HB_AAT_LAYOUT_NO_SELECTOR_INDEX</h3>
+<pre class="programlisting">#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX            0xFFFFu
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-feature-type-t"></a><h3>enum hb_aat_layout_feature_type_t</h3>
+<div class="refsect3">
+<a name="hb-aat-layout-feature-type-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-INVALID:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_INVALID</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-ALL-TYPOGRAPHIC:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-LIGATURES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CURISVE-CONNECTION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-LETTER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-VERTICAL-SUBSTITUTION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-LINGUISTIC-REARRANGEMENT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-NUMBER-SPACING:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-SMART-SWASH-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-DIACRITICS-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-VERTICAL-POSITION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-FRACTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-OVERLAPPING-CHARACTERS-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-TYPOGRAPHIC-EXTRAS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-MATHEMATICAL-EXTRAS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-ORNAMENT-SETS-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CHARACTER-ALTERNATIVES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-DESIGN-COMPLEXITY-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-STYLE-OPTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CHARACTER-SHAPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-NUMBER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-TEXT-SPACING:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-TRANSLITERATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-ANNOTATION-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-KANA-SPACING-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-IDEOGRAPHIC-SPACING-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-UNICODE-DECOMPOSITION-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-RUBY-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CJK-SYMBOL-ALTERNATIVES-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-IDEOGRAPHIC-ALTERNATIVES-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CJK-VERTICAL-ROMAN-PLACEMENT-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-ITALIC-CJK-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CASE-SENSITIVE-LAYOUT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-ALTERNATE-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-STYLISTIC-ALTERNATIVES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CONTEXTUAL-ALTERNATIVES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-LOWER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-UPPER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-LANGUAGE-TAG-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-CJK-ROMAN-SPACING-TYPE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-TYPE-MAX-VALUE:CAPS"></a>_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 2.2.0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-aat-layout-feature-selector-t"></a><h3>enum hb_aat_layout_feature_selector_t</h3>
+<div class="refsect3">
+<a name="hb-aat-layout-feature-selector-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INVALID:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-TYPE-FEATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-TYPE-FEATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-REQUIRED-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-REQUIRED-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-COMMON-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-COMMON-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-RARE-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-RARE-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LOGOS-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LOGOS-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-REBUS-PICTURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-REBUS-PICTURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DIPHTHONG-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DIPHTHONG-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SQUARED-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SQUARED-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ABBREV-SQUARED-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ABBREV-SQUARED-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SYMBOL-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SYMBOL-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HISTORICAL-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HISTORICAL-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-UNCONNECTED:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PARTIALLY-CONNECTED:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CURSIVE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-AND-LOWER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-LOWER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SMALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INITIAL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INITIAL-CAPS-AND-SMALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SUBSTITUTE-VERTICAL-FORMS-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SUBSTITUTE-VERTICAL-FORMS-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINGUISTIC-REARRANGEMENT-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINGUISTIC-REARRANGEMENT-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MONOSPACED-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-THIRD-WIDTH-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-QUARTER-WIDTH-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-INITIAL-SWASHES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-INITIAL-SWASHES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-FINAL-SWASHES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-FINAL-SWASHES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-INITIAL-SWASHES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-INITIAL-SWASHES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-FINAL-SWASHES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-FINAL-SWASHES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NON-FINAL-SWASHES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NON-FINAL-SWASHES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SHOW-DIACRITICS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HIDE-DIACRITICS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DECOMPOSE-DIACRITICS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NORMAL-POSITION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SUPERIORS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INFERIORS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ORDINALS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SCIENTIFIC-INFERIORS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-FRACTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-VERTICAL-FRACTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DIAGONAL-FRACTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PREVENT-OVERLAP-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PREVENT-OVERLAP-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHENS-TO-EM-DASH-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHENS-TO-EM-DASH-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-EN-DASH-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-EN-DASH-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASHED-ZERO-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASHED-ZERO-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FORM-INTERROBANG-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FORM-INTERROBANG-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SMART-QUOTES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SMART-QUOTES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIODS-TO-ELLIPSIS-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIODS-TO-ELLIPSIS-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-MINUS-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-MINUS-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ASTERISK-TO-MULTIPLY-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ASTERISK-TO-MULTIPLY-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASH-TO-DIVIDE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASH-TO-DIVIDE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INEQUALITY-LIGATURES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INEQUALITY-LIGATURES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPONENTS-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPONENTS-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MATHEMATICAL-GREEK-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MATHEMATICAL-GREEK-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ORNAMENTS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DINGBATS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PI-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FLEURONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DECORATIVE-BORDERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INTERNATIONAL-SYMBOLS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MATH-SYMBOLS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ALTERNATES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL1:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL2:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL3:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL4:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL5:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-STYLE-OPTIONS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DISPLAY-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ENGRAVED-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ILLUMINATED-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TITLING-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SIMPLIFIED-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1978-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1983-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1990-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-ONE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-TWO:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-THREE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-FOUR:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-FIVE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPERT-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS2004-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HOJO-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NLCCHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-NAMES-CHARACTERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-NUMBERS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MONOSPACED-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-THIRD-WIDTH-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-QUARTER-WIDTH-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALT-PROPORTIONAL-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALT-HALF-WIDTH-TEXT:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-TRANSLITERATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HIRAGANA-TO-KATAKANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-KATAKANA-TO-HIRAGANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-KANA-TO-ROMANIZATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMANIZATION-TO-HIRAGANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMANIZATION-TO-KATAKANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-ONE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-TWO:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-THREE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-BOX-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ROUNDED-BOX-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CIRCLE-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-CIRCLE-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PARENTHESIS-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIOD-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMAN-NUMERAL-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DIAMOND-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-BOX-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-ROUNDED-BOX-ANNOTATION:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-IDEOGRAPHS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-IDEOGRAPHS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-IDEOGRAPHS:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CANONICAL-COMPOSITION-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CANONICAL-COMPOSITION-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-COMPATIBILITY-COMPOSITION-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-COMPATIBILITY-COMPOSITION-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRANSCODING-COMPOSITION-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-TRANSCODING-COMPOSITION-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-RUBY-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-CJK-SYMBOL-ALTERNATIVES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-ONE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-TWO:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-THREE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-FOUR:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-FIVE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-IDEOGRAPHIC-ALTERNATIVES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-ONE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-TWO:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-THREE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-FOUR:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-FIVE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-VERTICAL-ROMAN-CENTERED:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-VERTICAL-ROMAN-HBASELINE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-CJK-ITALIC-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-LAYOUT-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-LAYOUT-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-SPACING-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-SPACING-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-HORIZ-KANA-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-HORIZ-KANA-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-VERT-KANA-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-VERT-KANA-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-STYLISTIC-ALTERNATES:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ONE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ONE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWO-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWO-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THREE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THREE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOUR-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOUR-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIVE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIVE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIX-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIX-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHT-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHT-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ELEVEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ELEVEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWELVE-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWELVE-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THIRTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THIRTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOURTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOURTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIFTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIFTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIXTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIXTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVENTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVENTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHTEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHTEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINETEEN-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINETEEN-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWENTY-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWENTY-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-ALTERNATES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-ALTERNATES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SWASH-ALTERNATES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-SWASH-ALTERNATES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-SWASH-ALTERNATES-ON:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-SWASH-ALTERNATES-OFF:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-LOWER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-SMALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-PETITE-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-UPPER-CASE:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-SMALL-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-PETITE-CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-CJK-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-CJK-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-CJK-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-CJK-ROMAN:CAPS"></a>HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-AAT-LAYOUT-FEATURE-SELECTOR-MAX-VALUE:CAPS"></a>_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 2.2.0</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index b3d9a76..9fa3967 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-blob: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-Buffers.html" title="Buffers">
-<link rel="next" href="harfbuzz-hb-face.html" title="hb-face">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="ch09.html" title="Core API">
+<link rel="next" href="harfbuzz-hb-buffer.html" title="hb-buffer">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-blob.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-Buffers.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-face.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch09.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-buffer.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-blob"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-blob.top_of_page"></a>hb-blob</span></h2>
-<p>hb-blob</p>
+<p>hb-blob — Binary data containers</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-blob.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_blob_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">╰──</span> hb_memory_mode_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-blob.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-blob.description"></a><h2>Description</h2>
+<p>Blobs wrap a chunk of binary data to handle lifecycle management of data
+while it is passed between client and HarfBuzz.  Blobs are primarily used
+to create font faces, but also to access font face tables, as well as
+pass around other binary data.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-blob.functions_details"></a><h2>Functions</h2>
@@ -272,7 +281,7 @@ hb_blob_create_from_file (<em class="parameter"><code>const <span class="type">c
 <a name="hb-blob-create-from-file.returns"></a><h4>Returns</h4>
 <p> A hb_blob_t pointer with the content of the file</p>
 </div>
-<p class="since">Since: 1.7.7</p>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -354,7 +363,7 @@ hb_blob_copy_writable_or_fail (<em class="parameter"><code><a class="link" href=
 <a name="hb-blob-copy-writable-or-fail.returns"></a><h4>Returns</h4>
 <p> New blob, or nullptr if allocation failed.</p>
 </div>
-<p class="since">Since: 1.8.0</p>
+<p class="since">Since: <a class="link" href="api-index-1-8-0.html#api-index-1.8.0">1.8.0</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -446,7 +455,7 @@ fails.</p>
 </tr>
 <tr>
 <td class="parameter_name"><p>length</p></td>
-<td class="parameter_description"><p>output length of the writable data. </p></td>
+<td class="parameter_description"><p> output length of the writable data. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 </tbody>
@@ -454,7 +463,7 @@ fails.</p>
 </div>
 <div class="refsect3">
 <a name="hb-blob-get-data-writable.returns"></a><h4>Returns</h4>
-<p>Writable blob data,
+<p> Writable blob data,
 or <code class="literal">NULL</code> if failed. </p>
 <p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=length]</span></p>
 </div>
@@ -469,7 +478,7 @@ hb_blob_get_empty (<em class="parameter"><code><span class="type">void</span></c
 <p>See TODO:link object types for more information.</p>
 <div class="refsect3">
 <a name="hb-blob-get-empty.returns"></a><h4>Returns</h4>
-<p>the empty blob. </p>
+<p> the empty blob. </p>
 <p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
 </div>
 <p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
@@ -712,6 +721,6 @@ is not needed anymore.</p></td>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-buffer.html b/docs/html/harfbuzz-hb-buffer.html
new file mode 100644 (file)
index 0000000..b9f3695
--- /dev/null
@@ -0,0 +1,3045 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-buffer: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-blob.html" title="hb-blob">
+<link rel="next" href="harfbuzz-hb-common.html" title="hb-common">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-buffer.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-buffer.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-blob.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-common.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-buffer"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-buffer.top_of_page"></a>hb-buffer</span></h2>
+<p>hb-buffer — Input and output buffers</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-create" title="hb_buffer_create ()">hb_buffer_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reference" title="hb_buffer_reference ()">hb_buffer_reference</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-empty" title="hb_buffer_get_empty ()">hb_buffer_get_empty</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-destroy" title="hb_buffer_destroy ()">hb_buffer_destroy</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reset" title="hb_buffer_reset ()">hb_buffer_reset</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-clear-contents" title="hb_buffer_clear_contents ()">hb_buffer_clear_contents</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()">hb_buffer_pre_allocate</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()">hb_buffer_allocation_successful</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add" title="hb_buffer_add ()">hb_buffer_add</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()">hb_buffer_add_codepoints</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf32" title="hb_buffer_add_utf32 ()">hb_buffer_add_utf32</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf16" title="hb_buffer_add_utf16 ()">hb_buffer_add_utf16</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-utf8" title="hb_buffer_add_utf8 ()">hb_buffer_add_utf8</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-latin1" title="hb_buffer_add_latin1 ()">hb_buffer_add_latin1</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-append" title="hb_buffer_append ()">hb_buffer_append</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()">hb_buffer_set_content_type</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="returnvalue">hb_buffer_content_type_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-content-type" title="hb_buffer_get_content_type ()">hb_buffer_get_content_type</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()">hb_buffer_set_direction</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="returnvalue">hb_direction_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-direction" title="hb_buffer_get_direction ()">hb_buffer_get_direction</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()">hb_buffer_set_script</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-script" title="hb_buffer_get_script ()">hb_buffer_get_script</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()">hb_buffer_set_language</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-language" title="hb_buffer_get_language ()">hb_buffer_get_language</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()">hb_buffer_set_flags</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="returnvalue">hb_buffer_flags_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-flags" title="hb_buffer_get_flags ()">hb_buffer_get_flags</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-cluster-level" title="hb_buffer_set_cluster_level ()">hb_buffer_set_cluster_level</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="returnvalue">hb_buffer_cluster_level_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-cluster-level" title="hb_buffer_get_cluster_level ()">hb_buffer_get_cluster_level</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-length" title="hb_buffer_set_length ()">hb_buffer_set_length</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-length" title="hb_buffer_get_length ()">hb_buffer_get_length</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()">hb_buffer_set_segment_properties</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()">hb_buffer_get_segment_properties</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()">hb_buffer_guess_segment_properties</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-unicode-funcs" title="hb_buffer_set_unicode_funcs ()">hb_buffer_set_unicode_funcs</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-unicode-funcs" title="hb_buffer_get_unicode_funcs ()">hb_buffer_get_unicode_funcs</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-user-data" title="hb_buffer_set_user_data ()">hb_buffer_set_user_data</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-user-data" title="hb_buffer_get_user_data ()">hb_buffer_get_user_data</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">hb_glyph_info_t</span> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-infos" title="hb_buffer_get_glyph_infos ()">hb_buffer_get_glyph_infos</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t"><span class="returnvalue">hb_glyph_position_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-positions" title="hb_buffer_get_glyph_positions ()">hb_buffer_get_glyph_positions</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-invisible-glyph" title="hb_buffer_get_invisible_glyph ()">hb_buffer_get_invisible_glyph</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-invisible-glyph" title="hb_buffer_set_invisible_glyph ()">hb_buffer_set_invisible_glyph</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()">hb_buffer_set_replacement_codepoint</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-replacement-codepoint" title="hb_buffer_get_replacement_codepoint ()">hb_buffer_get_replacement_codepoint</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-normalize-glyphs" title="hb_buffer_normalize_glyphs ()">hb_buffer_normalize_glyphs</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse" title="hb_buffer_reverse ()">hb_buffer_reverse</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-range" title="hb_buffer_reverse_range ()">hb_buffer_reverse_range</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reverse-clusters" title="hb_buffer_reverse_clusters ()">hb_buffer_reverse_clusters</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()">hb_buffer_serialize_glyphs</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()">hb_buffer_deserialize_glyphs</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="returnvalue">hb_buffer_serialize_format_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-from-string" title="hb_buffer_serialize_format_from_string ()">hb_buffer_serialize_format_from_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">char</span> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-to-string" title="hb_buffer_serialize_format_to_string ()">hb_buffer_serialize_format_to_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">char</span> **
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()">hb_buffer_serialize_list_formats</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-equal" title="hb_segment_properties_equal ()">hb_segment_properties_equal</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-hash" title="hb_segment_properties_hash ()">hb_segment_properties_hash</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t"><span class="returnvalue">hb_buffer_diff_flags_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff" title="hb_buffer_diff ()">hb_buffer_diff</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-message-func" title="hb_buffer_set_message_func ()">hb_buffer_set_message_func</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="returnvalue">hb_glyph_flags_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-info-get-glyph-flags" title="hb_glyph_info_get_glyph_flags ()">hb_glyph_info_get_glyph_flags</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()">*hb_buffer_message_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<a name="hb-buffer-t"></a><a name="hb-glyph-position-t"></a><a name="hb-segment-properties-t"></a><div class="refsect1">
+<a name="harfbuzz-hb-buffer.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS" title="HB_SEGMENT_PROPERTIES_DEFAULT">HB_SEGMENT_PROPERTIES_DEFAULT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</a></td>
+</tr>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t">hb_buffer_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct" title="hb_glyph_position_t">hb_glyph_position_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t">hb_buffer_content_type_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct" title="hb_segment_properties_t">hb_segment_properties_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t">hb_buffer_diff_flags_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+    <span class="lineart">├──</span> hb_buffer_t
+    <span class="lineart">├──</span> hb_glyph_position_t
+    <span class="lineart">╰──</span> hb_segment_properties_t
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <span class="lineart">├──</span> hb_buffer_cluster_level_t
+    <span class="lineart">├──</span> hb_buffer_content_type_t
+    <span class="lineart">╰──</span> hb_buffer_serialize_format_t
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
+    <span class="lineart">├──</span> hb_buffer_diff_flags_t
+    <span class="lineart">├──</span> hb_buffer_flags_t
+    <span class="lineart">├──</span> hb_buffer_serialize_flags_t
+    <span class="lineart">╰──</span> hb_glyph_flags_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.description"></a><h2>Description</h2>
+<p>Buffers serve dual role in HarfBuzz; they hold the input characters that are
+passed to <a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a>, and after shaping they hold the output glyphs.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-buffer-create"></a><h3>hb_buffer_create ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+hb_buffer_create (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Creates a new <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> with all properties to defaults.</p>
+<p><span class="annotation">[Xconstructor]</span></p>
+<div class="refsect3">
+<a name="hb-buffer-create.returns"></a><h4>Returns</h4>
+<p>A newly allocated <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> with a reference count of 1. The initial
+reference count should be released with <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-destroy" title="hb_buffer_destroy ()"><code class="function">hb_buffer_destroy()</code></a> when you are done
+using the <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. This function never returns <code class="literal">NULL</code>. If memory cannot
+be allocated, a special <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> object will be returned on which
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-allocation-successful" title="hb_buffer_allocation_successful ()"><code class="function">hb_buffer_allocation_successful()</code></a> returns <code class="literal">false</code>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-reference"></a><h3>hb_buffer_reference ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+hb_buffer_reference (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Increases the reference count on <em class="parameter"><code>buffer</code></em>
+ by one. This prevents <em class="parameter"><code>buffer</code></em>
+ from
+being destroyed until a matching call to <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-destroy" title="hb_buffer_destroy ()"><code class="function">hb_buffer_destroy()</code></a> is made.</p>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-buffer-reference.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-reference.returns"></a><h4>Returns</h4>
+<p>The referenced <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-empty"></a><h3>hb_buffer_get_empty ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="returnvalue">hb_buffer_t</span></a> *
+hb_buffer_get_empty (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-get-empty.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-destroy"></a><h3>hb_buffer_destroy ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_destroy (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Deallocate the <em class="parameter"><code>buffer</code></em>
+.
+Decreases the reference count on <em class="parameter"><code>buffer</code></em>
+ by one. If the result is zero, then
+<em class="parameter"><code>buffer</code></em>
+ and all associated resources are freed. See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reference" title="hb_buffer_reference ()"><code class="function">hb_buffer_reference()</code></a>.</p>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-buffer-destroy.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-reset"></a><h3>hb_buffer_reset ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_reset (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Resets the buffer to its initial status, as if it was just newly created
+with <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-create" title="hb_buffer_create ()"><code class="function">hb_buffer_create()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-reset.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-clear-contents"></a><h3>hb_buffer_clear_contents ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_clear_contents (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Similar to <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-reset" title="hb_buffer_reset ()"><code class="function">hb_buffer_reset()</code></a>, but does not clear the Unicode functions and
+the replacement code point.</p>
+<div class="refsect3">
+<a name="hb-buffer-clear-contents.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-11.html#api-index-0.9.11">0.9.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-pre-allocate"></a><h3>hb_buffer_pre_allocate ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_buffer_pre_allocate (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                        <em class="parameter"><code>unsigned <span class="type">int</span> size</code></em>);</pre>
+<p>Pre allocates memory for <em class="parameter"><code>buffer</code></em>
+ to fit at least <em class="parameter"><code>size</code></em>
+ number of items.</p>
+<div class="refsect3">
+<a name="hb-buffer-pre-allocate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>size</p></td>
+<td class="parameter_description"><p>number of items to pre allocate.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-pre-allocate.returns"></a><h4>Returns</h4>
+<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
+memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-allocation-successful"></a><h3>hb_buffer_allocation_successful ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_buffer_allocation_successful (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Check if allocating memory for the buffer succeeded.</p>
+<div class="refsect3">
+<a name="hb-buffer-allocation-successful.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-allocation-successful.returns"></a><h4>Returns</h4>
+<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
+memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add"></a><h3>hb_buffer_add ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+               <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> codepoint</code></em>,
+               <em class="parameter"><code>unsigned <span class="type">int</span> cluster</code></em>);</pre>
+<p>Appends a character with the Unicode value of <em class="parameter"><code>codepoint</code></em>
+ to <em class="parameter"><code>buffer</code></em>
+, and
+gives it the initial cluster value of <em class="parameter"><code>cluster</code></em>
+. Clusters can be any thing
+the client wants, they are usually used to refer to the index of the
+character in the input text stream and are output in
+<span class="type">hb_glyph_info_t.cluster</span> field.</p>
+<p>This function does not check the validity of <em class="parameter"><code>codepoint</code></em>
+, it is up to the
+caller to ensure it is a valid Unicode code point.</p>
+<div class="refsect3">
+<a name="hb-buffer-add.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>codepoint</p></td>
+<td class="parameter_description"><p>a Unicode code point.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cluster</p></td>
+<td class="parameter_description"><p>the cluster value of <em class="parameter"><code>codepoint</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add-codepoints"></a><h3>hb_buffer_add_codepoints ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add_codepoints (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                          <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *text</code></em>,
+                          <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
+                          <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
+                          <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
+<p>Appends characters from <em class="parameter"><code>text</code></em>
+ array to <em class="parameter"><code>buffer</code></em>
+. The <em class="parameter"><code>item_offset</code></em>
+ is the
+position of the first character from <em class="parameter"><code>text</code></em>
+ that will be appended, and
+<em class="parameter"><code>item_length</code></em>
+ is the number of character. When shaping part of a larger text
+(e.g. a run of text from a paragraph), instead of passing just the substring
+corresponding to the run, it is preferable to pass the whole
+paragraph and specify the run start and length as <em class="parameter"><code>item_offset</code></em>
+ and
+<em class="parameter"><code>item_length</code></em>
+, respectively, to give HarfBuzz the full context to be able,
+for example, to do cross-run Arabic shaping or properly handle combining
+marks at stat of run.</p>
+<p>This function does not check the validity of <em class="parameter"><code>text</code></em>
+, it is up to the caller
+to ensure it contains a valid Unicode code points.</p>
+<div class="refsect3">
+<a name="hb-buffer-add-codepoints.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>a <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to append characters to.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> an array of Unicode code points to append. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_length</p></td>
+<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
+, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_offset</p></td>
+<td class="parameter_description"><p>the offset of the first code point to add to the <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_length</p></td>
+<td class="parameter_description"><p>the number of code points to add to the <em class="parameter"><code>buffer</code></em>
+, or -1 for the
+end of <em class="parameter"><code>text</code></em>
+(assuming it is <code class="literal">NULL</code> terminated).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add-utf32"></a><h3>hb_buffer_add_utf32 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add_utf32 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                     <em class="parameter"><code>const <span class="type">uint32_t</span> *text</code></em>,
+                     <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
+                     <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
+                     <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
+<p>Replaces invalid UTF-32 characters with the <em class="parameter"><code>buffer</code></em>
+ replacement code point,
+see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-add-utf32.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> an array of UTF-32 characters to append. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_length</p></td>
+<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
+, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_offset</p></td>
+<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_length</p></td>
+<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
+, or -1 for the
+end of <em class="parameter"><code>text</code></em>
+(assuming it is <code class="literal">NULL</code> terminated).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add-utf16"></a><h3>hb_buffer_add_utf16 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add_utf16 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                     <em class="parameter"><code>const <span class="type">uint16_t</span> *text</code></em>,
+                     <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
+                     <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
+                     <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
+<p>Replaces invalid UTF-16 characters with the <em class="parameter"><code>buffer</code></em>
+ replacement code point,
+see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-add-utf16.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> an array of UTF-16 characters to append. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_length</p></td>
+<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
+, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_offset</p></td>
+<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_length</p></td>
+<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
+, or -1 for the
+end of <em class="parameter"><code>text</code></em>
+(assuming it is <code class="literal">NULL</code> terminated).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add-utf8"></a><h3>hb_buffer_add_utf8 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add_utf8 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                    <em class="parameter"><code>const <span class="type">char</span> *text</code></em>,
+                    <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
+                    <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
+                    <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>.</p>
+<p>Replaces invalid UTF-8 characters with the <em class="parameter"><code>buffer</code></em>
+ replacement code point,
+see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-add-utf8.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> an array of UTF-8
+characters to append. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_length</p></td>
+<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
+, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_offset</p></td>
+<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_length</p></td>
+<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
+, or -1 for the
+end of <em class="parameter"><code>text</code></em>
+(assuming it is <code class="literal">NULL</code> terminated).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-add-latin1"></a><h3>hb_buffer_add_latin1 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_add_latin1 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                      <em class="parameter"><code>const <span class="type">uint8_t</span> *text</code></em>,
+                      <em class="parameter"><code><span class="type">int</span> text_length</code></em>,
+                      <em class="parameter"><code>unsigned <span class="type">int</span> item_offset</code></em>,
+                      <em class="parameter"><code><span class="type">int</span> item_length</code></em>);</pre>
+<p>Similar to <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" title="hb_buffer_add_codepoints ()"><code class="function">hb_buffer_add_codepoints()</code></a>, but allows only access to first 256
+Unicode code points that can fit in 8-bit strings.</p>
+<div class="note">Has nothing to do with non-Unicode Latin-1 encoding.</div>
+<div class="refsect3">
+<a name="hb-buffer-add-latin1.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> an array of UTF-8
+characters to append. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_length][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_length</p></td>
+<td class="parameter_description"><p>the length of the <em class="parameter"><code>text</code></em>
+, or -1 if it is <code class="literal">NULL</code> terminated.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_offset</p></td>
+<td class="parameter_description"><p>the offset of the first character to add to the <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>item_length</p></td>
+<td class="parameter_description"><p>the number of characters to add to the <em class="parameter"><code>buffer</code></em>
+, or -1 for the
+end of <em class="parameter"><code>text</code></em>
+(assuming it is <code class="literal">NULL</code> terminated).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-39.html#api-index-0.9.39">0.9.39</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-append"></a><h3>hb_buffer_append ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_append (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *source</code></em>,
+                  <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
+                  <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>);</pre>
+<p>Append (part of) contents of another buffer to this buffer.</p>
+<div class="refsect3">
+<a name="hb-buffer-append.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>source</p></td>
+<td class="parameter_description"><p>source <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start</p></td>
+<td class="parameter_description"><p>start index into source buffer to copy.  Use 0 to copy from start of buffer.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>end</p></td>
+<td class="parameter_description"><p>end index into source buffer to copy.  Use (unsigned int) -1 to copy to end of buffer.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-content-type"></a><h3>hb_buffer_set_content_type ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_content_type (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="type">hb_buffer_content_type_t</span></a> content_type</code></em>);</pre>
+<p>Sets the type of <em class="parameter"><code>buffer</code></em>
+ contents, buffers are either empty, contain
+characters (before shaping) or glyphs (the result of shaping).</p>
+<div class="refsect3">
+<a name="hb-buffer-set-content-type.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>content_type</p></td>
+<td class="parameter_description"><p>the type of buffer contents to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-content-type"></a><h3>hb_buffer_get_content_type ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t"><span class="returnvalue">hb_buffer_content_type_t</span></a>
+hb_buffer_get_content_type (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-content-type" title="hb_buffer_set_content_type ()"><code class="function">hb_buffer_set_content_type()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-content-type.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-content-type.returns"></a><h4>Returns</h4>
+<p>The type of <em class="parameter"><code>buffer</code></em>
+contents.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-direction"></a><h3>hb_buffer_set_direction ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_direction (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> direction</code></em>);</pre>
+<p>Set the text flow direction of the buffer. No shaping can happen without
+setting <em class="parameter"><code>buffer</code></em>
+ direction, and it controls the visual direction for the
+output glyphs; for RTL direction the glyphs will be reversed. Many layout
+features depend on the proper setting of the direction, for example,
+reversing RTL text before shaping, then shaping with LTR direction is not
+the same as keeping the text in logical order and shaping with RTL
+direction.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-direction.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>direction</p></td>
+<td class="parameter_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-direction"></a><h3>hb_buffer_get_direction ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="returnvalue">hb_direction_t</span></a>
+hb_buffer_get_direction (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a></p>
+<div class="refsect3">
+<a name="hb-buffer-get-direction.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-direction.returns"></a><h4>Returns</h4>
+<p>The direction of the <em class="parameter"><code>buffer</code></em>
+.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-script"></a><h3>hb_buffer_set_script ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> script</code></em>);</pre>
+<p>Sets the script of <em class="parameter"><code>buffer</code></em>
+ to <em class="parameter"><code>script</code></em>
+.</p>
+<p>Script is crucial for choosing the proper shaping behaviour for scripts that
+require it (e.g. Arabic) and the which OpenType features defined in the font
+to be applied.</p>
+<p>You can pass one of the predefined <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> values, or use
+<a class="link" href="harfbuzz-hb-common.html#hb-script-from-string" title="hb_script_from_string ()"><code class="function">hb_script_from_string()</code></a> or <a class="link" href="harfbuzz-hb-common.html#hb-script-from-iso15924-tag" title="hb_script_from_iso15924_tag ()"><code class="function">hb_script_from_iso15924_tag()</code></a> to get the
+corresponding script from an ISO 15924 script tag.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-script.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>script</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> to set.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-script"></a><h3>hb_buffer_get_script ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
+hb_buffer_get_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-script.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-script.returns"></a><h4>Returns</h4>
+<p>The <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> of the <em class="parameter"><code>buffer</code></em>
+.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-language"></a><h3>hb_buffer_set_language ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>);</pre>
+<p>Sets the language of <em class="parameter"><code>buffer</code></em>
+ to <em class="parameter"><code>language</code></em>
+.</p>
+<p>Languages are crucial for selecting which OpenType feature to apply to the
+buffer which can result in applying language-specific behaviour. Languages
+are orthogonal to the scripts, and though they are related, they are
+different concepts and should not be confused with each other.</p>
+<p>Use <a class="link" href="harfbuzz-hb-common.html#hb-language-from-string" title="hb_language_from_string ()"><code class="function">hb_language_from_string()</code></a> to convert from BCP 47 language tags to
+<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-language.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p>an hb_language_t to set.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-language"></a><h3>hb_buffer_get_language ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
+hb_buffer_get_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-language.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-language.returns"></a><h4>Returns</h4>
+<p>The <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> of the buffer. Must not be freed by the caller. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-flags"></a><h3>hb_buffer_set_flags ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_flags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="type">hb_buffer_flags_t</span></a> flags</code></em>);</pre>
+<p>Sets <em class="parameter"><code>buffer</code></em>
+ flags to <em class="parameter"><code>flags</code></em>
+. See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="type">hb_buffer_flags_t</span></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-flags.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>flags</p></td>
+<td class="parameter_description"><p>the buffer flags to set.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-flags"></a><h3>hb_buffer_get_flags ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t"><span class="returnvalue">hb_buffer_flags_t</span></a>
+hb_buffer_get_flags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-flags" title="hb_buffer_set_flags ()"><code class="function">hb_buffer_set_flags()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-flags.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-flags.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+flags.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-cluster-level"></a><h3>hb_buffer_set_cluster_level ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_cluster_level (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="type">hb_buffer_cluster_level_t</span></a> cluster_level</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-set-cluster-level.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-42.html#api-index-0.9.42">0.9.42</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-cluster-level"></a><h3>hb_buffer_get_cluster_level ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t"><span class="returnvalue">hb_buffer_cluster_level_t</span></a>
+hb_buffer_get_cluster_level (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-get-cluster-level.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-42.html#api-index-0.9.42">0.9.42</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-length"></a><h3>hb_buffer_set_length ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_buffer_set_length (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                      <em class="parameter"><code>unsigned <span class="type">int</span> length</code></em>);</pre>
+<p>Similar to <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-pre-allocate" title="hb_buffer_pre_allocate ()"><code class="function">hb_buffer_pre_allocate()</code></a>, but clears any new items added at the
+end.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-length.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>length</p></td>
+<td class="parameter_description"><p>the new length of <em class="parameter"><code>buffer</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-set-length.returns"></a><h4>Returns</h4>
+<p><code class="literal">true</code> if <em class="parameter"><code>buffer</code></em>
+memory allocation succeeded, <code class="literal">false</code> otherwise.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-length"></a><h3>hb_buffer_get_length ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_buffer_get_length (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Returns the number of items in the buffer.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-length.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-length.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+length.
+The value valid as long as buffer has not been modified.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-segment-properties"></a><h3>hb_buffer_set_segment_properties ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                                  <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>);</pre>
+<p>Sets the segment properties of the buffer, a shortcut for calling
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a>, <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a> and
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a> individually.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-segment-properties.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>props</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to use.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-segment-properties"></a><h3>hb_buffer_get_segment_properties ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_get_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>);</pre>
+<p>Sets <em class="parameter"><code>props</code></em>
+ to the <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> of <em class="parameter"><code>buffer</code></em>
+.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-segment-properties.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>props</p></td>
+<td class="parameter_description"><p> the output <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-guess-segment-properties"></a><h3>hb_buffer_guess_segment_properties ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_guess_segment_properties (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Sets unset buffer segment properties based on buffer Unicode
+contents.  If buffer is not empty, it must have content type
+<a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"><code class="literal">HB_BUFFER_CONTENT_TYPE_UNICODE</code></a>.</p>
+<p>If buffer script is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-SCRIPT-INVALID:CAPS"><code class="literal">HB_SCRIPT_INVALID</code></a>), it
+will be set to the Unicode script of the first character in
+the buffer that has a script other than <a class="link" href="harfbuzz-hb-common.html#HB-SCRIPT-COMMON:CAPS"><code class="literal">HB_SCRIPT_COMMON</code></a>,
+<a class="link" href="harfbuzz-hb-common.html#HB-SCRIPT-INHERITED:CAPS"><code class="literal">HB_SCRIPT_INHERITED</code></a>, and <a class="link" href="harfbuzz-hb-common.html#HB-SCRIPT-UNKNOWN:CAPS"><code class="literal">HB_SCRIPT_UNKNOWN</code></a>.</p>
+<p>Next, if buffer direction is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-INVALID:CAPS"><code class="literal">HB_DIRECTION_INVALID</code></a>),
+it will be set to the natural horizontal direction of the
+buffer script as returned by <a class="link" href="harfbuzz-hb-common.html#hb-script-get-horizontal-direction" title="hb_script_get_horizontal_direction ()"><code class="function">hb_script_get_horizontal_direction()</code></a>.
+If <a class="link" href="harfbuzz-hb-common.html#hb-script-get-horizontal-direction" title="hb_script_get_horizontal_direction ()"><code class="function">hb_script_get_horizontal_direction()</code></a> returns <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-INVALID:CAPS"><code class="literal">HB_DIRECTION_INVALID</code></a>,
+then <a class="link" href="harfbuzz-hb-common.html#HB-DIRECTION-LTR:CAPS"><code class="literal">HB_DIRECTION_LTR</code></a> is used.</p>
+<p>Finally, if buffer language is not set (ie. is <a class="link" href="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS" title="HB_LANGUAGE_INVALID"><code class="literal">HB_LANGUAGE_INVALID</code></a>),
+it will be set to the process's default language as returned by
+<a class="link" href="harfbuzz-hb-common.html#hb-language-get-default" title="hb_language_get_default ()"><code class="function">hb_language_get_default()</code></a>.  This may change in the future by
+taking buffer script into consideration when choosing a language.
+Note that <a class="link" href="harfbuzz-hb-common.html#hb-language-get-default" title="hb_language_get_default ()"><code class="function">hb_language_get_default()</code></a> is NOT threadsafe the first time
+it is called.  See documentation for that function for details.</p>
+<div class="refsect3">
+<a name="hb-buffer-guess-segment-properties.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-unicode-funcs"></a><h3>hb_buffer_set_unicode_funcs ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_unicode_funcs (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *unicode_funcs</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-set-unicode-funcs.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-unicode-funcs"></a><h3>hb_buffer_get_unicode_funcs ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
+hb_buffer_get_unicode_funcs (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-get-unicode-funcs.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-user-data"></a><h3>hb_buffer_set_user_data ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_buffer_set_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>,
+                         <em class="parameter"><code><span class="type">void</span> *data</code></em>,
+                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>,
+                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="type">hb_bool_t</span></a> replace</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-buffer-set-user-data.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-user-data"></a><h3>hb_buffer_get_user_data ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span> *
+hb_buffer_get_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-buffer-get-user-data.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-glyph-infos"></a><h3>hb_buffer_get_glyph_infos ()</h3>
+<pre class="programlisting"><span class="returnvalue">hb_glyph_info_t</span> *
+hb_buffer_get_glyph_infos (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                           <em class="parameter"><code>unsigned <span class="type">int</span> *length</code></em>);</pre>
+<p>Returns <em class="parameter"><code>buffer</code></em>
+ glyph information array.  Returned pointer
+is valid as long as <em class="parameter"><code>buffer</code></em>
+ contents are not modified.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-glyph-infos.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>length</p></td>
+<td class="parameter_description"><p> output array length. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-glyph-infos.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+glyph information array.
+The value valid as long as buffer has not been modified. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=length]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-glyph-positions"></a><h3>hb_buffer_get_glyph_positions ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t"><span class="returnvalue">hb_glyph_position_t</span></a> *
+hb_buffer_get_glyph_positions (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                               <em class="parameter"><code>unsigned <span class="type">int</span> *length</code></em>);</pre>
+<p>Returns <em class="parameter"><code>buffer</code></em>
+ glyph position array.  Returned pointer
+is valid as long as <em class="parameter"><code>buffer</code></em>
+ contents are not modified.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-glyph-positions.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>length</p></td>
+<td class="parameter_description"><p> output length. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-glyph-positions.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+glyph position array.
+The value valid as long as buffer has not been modified. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=length]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-invisible-glyph"></a><h3>hb_buffer_get_invisible_glyph ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+hb_buffer_get_invisible_glyph (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-invisible-glyph" title="hb_buffer_set_invisible_glyph ()"><code class="function">hb_buffer_set_invisible_glyph()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-invisible-glyph.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-invisible-glyph.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+invisible <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a>.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-invisible-glyph"></a><h3>hb_buffer_set_invisible_glyph ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_invisible_glyph (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                               <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> invisible</code></em>);</pre>
+<p>Sets the <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> that replaces invisible characters in
+the shaping result.  If set to zero (default), the glyph for the
+U+0020 SPACE character is used.  Otherwise, this value is used
+verbatim.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-invisible-glyph.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>invisible</p></td>
+<td class="parameter_description"><p>the invisible <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-replacement-codepoint"></a><h3>hb_buffer_set_replacement_codepoint ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_replacement_codepoint (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> replacement</code></em>);</pre>
+<p>Sets the <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> that replaces invalid entries for a given encoding
+when adding text to <em class="parameter"><code>buffer</code></em>
+.</p>
+<p>Default is <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" title="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT"><code class="literal">HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-set-replacement-codepoint.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>replacement</p></td>
+<td class="parameter_description"><p>the replacement <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-get-replacement-codepoint"></a><h3>hb_buffer_get_replacement_codepoint ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+hb_buffer_get_replacement_codepoint (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" title="hb_buffer_set_replacement_codepoint ()"><code class="function">hb_buffer_set_replacement_codepoint()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-get-replacement-codepoint.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-get-replacement-codepoint.returns"></a><h4>Returns</h4>
+<p>The <em class="parameter"><code>buffer</code></em>
+replacement <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a>.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-normalize-glyphs"></a><h3>hb_buffer_normalize_glyphs ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_normalize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Reorders a glyph buffer to have canonical in-cluster glyph order / position.
+The resulting clusters should behave identical to pre-reordering clusters.</p>
+<div class="note">This has nothing to do with Unicode normalization.</div>
+<div class="refsect3">
+<a name="hb-buffer-normalize-glyphs.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-reverse"></a><h3>hb_buffer_reverse ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_reverse (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Reverses buffer contents.</p>
+<div class="refsect3">
+<a name="hb-buffer-reverse.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-reverse-range"></a><h3>hb_buffer_reverse_range ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_reverse_range (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                         <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
+                         <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>);</pre>
+<p>Reverses buffer contents between start to end.</p>
+<div class="refsect3">
+<a name="hb-buffer-reverse-range.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start</p></td>
+<td class="parameter_description"><p>start index.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>end</p></td>
+<td class="parameter_description"><p>end index.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-41.html#api-index-0.9.41">0.9.41</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-reverse-clusters"></a><h3>hb_buffer_reverse_clusters ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_reverse_clusters (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>);</pre>
+<p>Reverses buffer clusters.  That is, the buffer contents are
+reversed, then each cluster (consecutive items having the
+same cluster number) are reversed again.</p>
+<div class="refsect3">
+<a name="hb-buffer-reverse-clusters.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-glyphs"></a><h3>hb_buffer_serialize_glyphs ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_buffer_serialize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                            <em class="parameter"><code>unsigned <span class="type">int</span> start</code></em>,
+                            <em class="parameter"><code>unsigned <span class="type">int</span> end</code></em>,
+                            <em class="parameter"><code><span class="type">char</span> *buf</code></em>,
+                            <em class="parameter"><code>unsigned <span class="type">int</span> buf_size</code></em>,
+                            <em class="parameter"><code>unsigned <span class="type">int</span> *buf_consumed</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t"><span class="type">hb_buffer_serialize_flags_t</span></a> flags</code></em>);</pre>
+<p>Serializes <em class="parameter"><code>buffer</code></em>
+ into a textual representation of its glyph content,
+useful for showing the contents of the buffer, for example during debugging.
+There are currently two supported serialization formats:</p>
+<div class="refsect3">
+<a name="id-1.3.4.3.11.48.5"></a><h4>text</h4>
+<p>A human-readable, plain text format.
+The serialized glyphs will look something like:</p>
+<p><code class="literal">
+[uni0651=0@518,0+0|uni0628=0+1897]
+</code></p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>The serialized glyphs are delimited with <code class="literal">[</code> and <code class="literal">]</code>.</p></li>
+<li class="listitem"><p>Glyphs are separated with <code class="literal">|</code></p></li>
+<li class="listitem">
+<p>Each glyph starts with glyph name, or glyph index if
+<a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES</span></a> flag is set. Then,</p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
+<li class="listitem"><p>If <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS</span></a> is not set, <code class="literal">=</code> then <span class="type">hb_glyph_info_t.cluster</span>.</p></li>
+<li class="listitem">
+<p>If <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS</span></a> is not set, the <a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> in the format:</p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: square; ">
+<li class="listitem"><p>If both <span class="type">hb_glyph_position_t.x_offset</span> and <span class="type">hb_glyph_position_t.y_offset</span> are not 0, <code class="literal">@x_offset,y_offset</code>. Then,</p></li>
+<li class="listitem"><p><code class="literal">+x_advance</code>, then <code class="literal">,y_advance</code> if <span class="type">hb_glyph_position_t.y_advance</span> is not 0. Then,</p></li>
+</ul></div>
+</li>
+<li class="listitem"><p>If <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"><span class="type">HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS</span></a> is set, the
+<span class="type">hb_glyph_extents_t</span> in the format
+<code class="literal">&lt;x_bearing,y_bearing,width,height&gt;</code></p></li>
+</ul></div>
+</li>
+</ul></div>
+</div>
+<div class="refsect3">
+<a name="id-1.3.4.3.11.48.6"></a><h4>json</h4>
+<p>TODO.</p>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-serialize-glyphs.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> buffer.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start</p></td>
+<td class="parameter_description"><p>the first item in <em class="parameter"><code>buffer</code></em>
+to serialize.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>end</p></td>
+<td class="parameter_description"><p>the last item in <em class="parameter"><code>buffer</code></em>
+to serialize.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p> output string to
+write serialized buffer into. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_size][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf_size</p></td>
+<td class="parameter_description"><p>the size of <em class="parameter"><code>buf</code></em>
+.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf_consumed</p></td>
+<td class="parameter_description"><p> if not <code class="literal">NULL</code>, will be set to the number of byes written into <em class="parameter"><code>buf</code></em>
+. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p> the <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> used to shape this buffer, needed to
+read glyph names and extents. If <code class="literal">NULL</code>, and empty font will be used. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>format</p></td>
+<td class="parameter_description"><p>the <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> to use for formatting the output.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>flags</p></td>
+<td class="parameter_description"><p>the <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t"><span class="type">hb_buffer_serialize_flags_t</span></a> that control what glyph properties
+to serialize.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-serialize-glyphs.returns"></a><h4>Returns</h4>
+<p>The number of serialized items.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-deserialize-glyphs"></a><h3>hb_buffer_deserialize_glyphs ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_buffer_deserialize_glyphs (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                              <em class="parameter"><code>const <span class="type">char</span> *buf</code></em>,
+                              <em class="parameter"><code><span class="type">int</span> buf_len</code></em>,
+                              <em class="parameter"><code>const <span class="type">char</span> **end_ptr</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-deserialize-glyphs.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> buffer.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_len]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>end_ptr</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-format-from-string"></a><h3>hb_buffer_serialize_format_from_string ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="returnvalue">hb_buffer_serialize_format_t</span></a>
+hb_buffer_serialize_format_from_string
+                               (<em class="parameter"><code>const <span class="type">char</span> *str</code></em>,
+                                <em class="parameter"><code><span class="type">int</span> len</code></em>);</pre>
+<p>Parses a string into an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>. Does not check if
+<em class="parameter"><code>str</code></em>
+ is a valid buffer serialization format, use
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-list-formats" title="hb_buffer_serialize_list_formats ()"><code class="function">hb_buffer_serialize_list_formats()</code></a> to get the list of supported formats.</p>
+<div class="refsect3">
+<a name="hb-buffer-serialize-format-from-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>str</p></td>
+<td class="parameter_description"><p> a string to parse. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>length of <em class="parameter"><code>str</code></em>
+, or -1 if string is <code class="literal">NULL</code> terminated</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-serialize-format-from-string.returns"></a><h4>Returns</h4>
+<p>The parsed <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-format-to-string"></a><h3>hb_buffer_serialize_format_to_string ()</h3>
+<pre class="programlisting">const <span class="returnvalue">char</span> *
+hb_buffer_serialize_format_to_string (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> format</code></em>);</pre>
+<p>Converts <em class="parameter"><code>format</code></em>
+ to the string corresponding it, or <code class="literal">NULL</code> if it is not a valid
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-serialize-format-to-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>format</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t"><span class="type">hb_buffer_serialize_format_t</span></a> to convert.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-buffer-serialize-format-to-string.returns"></a><h4>Returns</h4>
+<p>A <code class="literal">NULL</code> terminated string corresponding to <em class="parameter"><code>format</code></em>
+. Should not be freed. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-list-formats"></a><h3>hb_buffer_serialize_list_formats ()</h3>
+<pre class="programlisting">const <span class="returnvalue">char</span> **
+hb_buffer_serialize_list_formats (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Returns a list of supported buffer serialization formats.</p>
+<div class="refsect3">
+<a name="hb-buffer-serialize-list-formats.returns"></a><h4>Returns</h4>
+<p>A string array of buffer serialization formats. Should not be freed. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-segment-properties-equal"></a><h3>hb_segment_properties_equal ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_segment_properties_equal (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *a</code></em>,
+                             <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *b</code></em>);</pre>
+<p>Checks the equality of two <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a>'s.</p>
+<div class="refsect3">
+<a name="hb-segment-properties-equal.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>a</p></td>
+<td class="parameter_description"><p>first <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to compare.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>b</p></td>
+<td class="parameter_description"><p>second <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to compare.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-segment-properties-equal.returns"></a><h4>Returns</h4>
+<p><code class="literal">true</code> if all properties of <em class="parameter"><code>a</code></em>
+equal those of <em class="parameter"><code>b</code></em>
+, false otherwise.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-segment-properties-hash"></a><h3>hb_segment_properties_hash ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_segment_properties_hash (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *p</code></em>);</pre>
+<p>Creates a hash representing <em class="parameter"><code>p</code></em>
+.</p>
+<div class="refsect3">
+<a name="hb-segment-properties-hash.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>p</p></td>
+<td class="parameter_description"><p><a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> to hash.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-segment-properties-hash.returns"></a><h4>Returns</h4>
+<p>A hash of <em class="parameter"><code>p</code></em>
+.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-7.html#api-index-0.9.7">0.9.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-diff"></a><h3>hb_buffer_diff ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t"><span class="returnvalue">hb_buffer_diff_flags_t</span></a>
+hb_buffer_diff (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *reference</code></em>,
+                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> dottedcircle_glyph</code></em>,
+                <em class="parameter"><code>unsigned <span class="type">int</span> position_fuzz</code></em>);</pre>
+<p>If dottedcircle_glyph is (hb_codepoint_t) -1 then <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"><code class="literal">HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT</code></a>
+and <a class="link" href="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"><code class="literal">HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT</code></a> are never returned.  This should be used by most
+callers if just comparing two buffers is needed.</p>
+<div class="refsect3">
+<a name="hb-buffer-diff.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>a buffer.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>reference</p></td>
+<td class="parameter_description"><p>other buffer to compare to.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>dottedcircle_glyph</p></td>
+<td class="parameter_description"><p>glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>position_fuzz</p></td>
+<td class="parameter_description"><p>allowed absolute difference in position values.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-set-message-func"></a><h3>hb_buffer_set_message_func ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_buffer_set_message_func (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-message-func-t" title="hb_buffer_message_func_t ()"><span class="type">hb_buffer_message_func_t</span></a> func</code></em>,
+                            <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-buffer-set-message-func.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>func</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-1-3.html#api-index-1.1.3">1.1.3</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-glyph-info-get-glyph-flags"></a><h3>hb_glyph_info_get_glyph_flags ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="returnvalue">hb_glyph_flags_t</span></a>
+hb_glyph_info_get_glyph_flags (<em class="parameter"><code>const <span class="type">hb_glyph_info_t</span> *info</code></em>);</pre>
+<p>Returns glyph flags encoded within a <span class="type">hb_glyph_info_t</span>.</p>
+<div class="refsect3">
+<a name="hb-glyph-info-get-glyph-flags.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>info</p></td>
+<td class="parameter_description"><p>a <span class="type">hb_glyph_info_t</span>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-glyph-info-get-glyph-flags.returns"></a><h4>Returns</h4>
+<p>The <a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t"><span class="type">hb_glyph_flags_t</span></a> encoded within <em class="parameter"><code>info</code></em>
+.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-message-func-t"></a><h3>hb_buffer_message_func_t ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+<span class="c_punctuation">(</span>*hb_buffer_message_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                             <em class="parameter"><code>const <span class="type">char</span> *message</code></em>,
+                             <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-buffer.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="HB-SEGMENT-PROPERTIES-DEFAULT:CAPS"></a><h3>HB_SEGMENT_PROPERTIES_DEFAULT</h3>
+<pre class="programlisting">#define             HB_SEGMENT_PROPERTIES_DEFAULT</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS"></a><h3>HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT</h3>
+<pre class="programlisting">#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
+</pre>
+<p>The default code point for replacing invalid characters in a given encoding.
+Set to U+FFFD REPLACEMENT CHARACTER.</p>
+<p class="since">Since: <a class="link" href="api-index-0-9-31.html#api-index-0.9.31">0.9.31</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-t"></a><h3>hb_buffer_t</h3>
+<pre class="programlisting">typedef struct hb_buffer_t hb_buffer_t;
+</pre>
+<p>The main structure holding the input text and its properties before shaping,
+and output glyphs and their information after shaping.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-glyph-flags-t"></a><h3>enum hb_glyph_flags_t</h3>
+<div class="refsect3">
+<a name="hb-glyph-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-GLYPH-FLAG-UNSAFE-TO-BREAK:CAPS"></a>HB_GLYPH_FLAG_UNSAFE_TO_BREAK</p></td>
+<td class="enum_member_description">
+<p>Indicates that if input text is broken at the
+                                  beginning of the cluster this glyph is part of,
+                                  then both sides need to be re-shaped, as the
+                                  result might be different.  On the flip side,
+                                  it means that when this flag is not present,
+                                  then it's safe to break the glyph-run at the
+                                  beginning of this cluster, and the two sides
+                                  represent the exact same result one would get
+                                  if breaking input text at the beginning of
+                                  this cluster and shaping the two sides
+                                  separately.  This can be used to optimize
+                                  paragraph layout, by avoiding re-shaping
+                                  of each line after line-breaking, or limiting
+                                  the reshaping to a small piece around the
+                                  breaking point only.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-GLYPH-FLAG-DEFINED:CAPS"></a>HB_GLYPH_FLAG_DEFINED</p></td>
+<td class="enum_member_description">
+<p>All the currently defined flags.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-5-0.html#api-index-1.5.0">1.5.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-glyph-position-t-struct"></a><h3>hb_glyph_position_t</h3>
+<pre class="programlisting">typedef struct {
+  hb_position_t  x_advance;
+  hb_position_t  y_advance;
+  hb_position_t  x_offset;
+  hb_position_t  y_offset;
+} hb_glyph_position_t;
+</pre>
+<p>The <a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> is the structure that holds the positions of the
+glyph in both horizontal and vertical directions. All positions in
+<a class="link" href="harfbuzz-hb-buffer.html#hb-glyph-position-t"><span class="type">hb_glyph_position_t</span></a> are relative to the current point.</p>
+<div class="refsect3">
+<a name="hb-glyph-position-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.x-advance"></a>x_advance</code></em>;</p></td>
+<td class="struct_member_description"><p>how much the line advances after drawing this glyph when setting
+text in horizontal direction.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.y-advance"></a>y_advance</code></em>;</p></td>
+<td class="struct_member_description"><p>how much the line advances after drawing this glyph when setting
+text in vertical direction.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.x-offset"></a>x_offset</code></em>;</p></td>
+<td class="struct_member_description"><p>how much the glyph moves on the X-axis before drawing it, this
+should not affect how much the line advances.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> <em class="structfield"><code><a name="hb-glyph-position-t-struct.y-offset"></a>y_offset</code></em>;</p></td>
+<td class="struct_member_description"><p>how much the glyph moves on the Y-axis before drawing it, this
+should not affect how much the line advances.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-content-type-t"></a><h3>enum hb_buffer_content_type_t</h3>
+<div class="refsect3">
+<a name="hb-buffer-content-type-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-INVALID:CAPS"></a>HB_BUFFER_CONTENT_TYPE_INVALID</p></td>
+<td class="enum_member_description">
+<p>Initial value for new buffer.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"></a>HB_BUFFER_CONTENT_TYPE_UNICODE</p></td>
+<td class="enum_member_description">
+<p>The buffer contains input characters (before shaping).</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CONTENT-TYPE-GLYPHS:CAPS"></a>HB_BUFFER_CONTENT_TYPE_GLYPHS</p></td>
+<td class="enum_member_description">
+<p>The buffer contains output glyphs (after shaping).</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-flags-t"></a><h3>enum hb_buffer_flags_t</h3>
+<div class="refsect3">
+<a name="hb-buffer-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-DEFAULT:CAPS"></a>HB_BUFFER_FLAG_DEFAULT</p></td>
+<td class="enum_member_description">
+<p>the default buffer flag.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-BOT:CAPS"></a>HB_BUFFER_FLAG_BOT</p></td>
+<td class="enum_member_description">
+<p>flag indicating that special handling of the beginning
+                     of text paragraph can be applied to this buffer. Should usually
+                     be set, unless you are passing to the buffer only part
+                     of the text without the full context.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-EOT:CAPS"></a>HB_BUFFER_FLAG_EOT</p></td>
+<td class="enum_member_description">
+<p>flag indicating that special handling of the end of text
+                     paragraph can be applied to this buffer, similar to
+                     <em class="parameter"><code>HB_BUFFER_FLAG_BOT</code></em>
+.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-PRESERVE-DEFAULT-IGNORABLES:CAPS"></a>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</p></td>
+<td class="enum_member_description">
+<p>                     flag indication that character with Default_Ignorable
+                     Unicode property should use the corresponding glyph
+                     from the font, instead of hiding them (done by
+                     replacing them with the space glyph and zeroing the
+                     advance width.)  This flag takes precedence over
+                     <em class="parameter"><code>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</code></em>
+.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-FLAG-REMOVE-DEFAULT-IGNORABLES:CAPS"></a>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</p></td>
+<td class="enum_member_description">
+<p>                     flag indication that character with Default_Ignorable
+                     Unicode property should be removed from glyph string
+                     instead of hiding them (done by replacing them with the
+                     space glyph and zeroing the advance width.)
+                     <em class="parameter"><code>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</code></em>
+ takes
+                     precedence over this flag. Since: 1.8.0</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-20.html#api-index-0.9.20">0.9.20</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-cluster-level-t"></a><h3>enum hb_buffer_cluster_level_t</h3>
+<div class="refsect3">
+<a name="hb-buffer-cluster-level-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-MONOTONE-GRAPHEMES:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</p></td>
+<td class="enum_member_description">
+<p>Return cluster values grouped by graphemes into
+  monotone order.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-MONOTONE-CHARACTERS:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS</p></td>
+<td class="enum_member_description">
+<p>Return cluster values grouped into monotone order.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-CHARACTERS:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_CHARACTERS</p></td>
+<td class="enum_member_description">
+<p>Don't group cluster values.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-CLUSTER-LEVEL-DEFAULT:CAPS"></a>HB_BUFFER_CLUSTER_LEVEL_DEFAULT</p></td>
+<td class="enum_member_description">
+<p>Default cluster level,
+  equal to <em class="parameter"><code>HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</code></em>
+.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-42.html#api-index-0.9.42">0.9.42</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-segment-properties-t-struct"></a><h3>hb_segment_properties_t</h3>
+<pre class="programlisting">typedef struct {
+  hb_direction_t  direction;
+  hb_script_t     script;
+  hb_language_t   language;
+} hb_segment_properties_t;
+</pre>
+<p>The structure that holds various text properties of an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a>. Can be
+set and retrieved using <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-segment-properties" title="hb_buffer_set_segment_properties ()"><code class="function">hb_buffer_set_segment_properties()</code></a> and
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-get-segment-properties" title="hb_buffer_get_segment_properties ()"><code class="function">hb_buffer_get_segment_properties()</code></a>, respectively.</p>
+<div class="refsect3">
+<a name="hb-segment-properties-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.direction"></a>direction</code></em>;</p></td>
+<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> of the buffer, see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-direction" title="hb_buffer_set_direction ()"><code class="function">hb_buffer_set_direction()</code></a>.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.script"></a>script</code></em>;</p></td>
+<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> of the buffer, see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-script" title="hb_buffer_set_script ()"><code class="function">hb_buffer_set_script()</code></a>.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> <em class="structfield"><code><a name="hb-segment-properties-t-struct.language"></a>language</code></em>;</p></td>
+<td class="struct_member_description"><p>the <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> of the buffer, see <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-set-language" title="hb_buffer_set_language ()"><code class="function">hb_buffer_set_language()</code></a>.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-format-t"></a><h3>enum hb_buffer_serialize_format_t</h3>
+<p>The buffer serialization and de-serialization format used in
+<a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()"><code class="function">hb_buffer_serialize_glyphs()</code></a> and <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-deserialize-glyphs" title="hb_buffer_deserialize_glyphs ()"><code class="function">hb_buffer_deserialize_glyphs()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-serialize-format-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-TEXT:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_TEXT</p></td>
+<td class="enum_member_description">
+<p>a human-readable, plain text format.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-JSON:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_JSON</p></td>
+<td class="enum_member_description">
+<p>a machine-readable JSON format.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FORMAT-INVALID:CAPS"></a>HB_BUFFER_SERIALIZE_FORMAT_INVALID</p></td>
+<td class="enum_member_description">
+<p>invalid format.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-serialize-flags-t"></a><h3>enum hb_buffer_serialize_flags_t</h3>
+<p>Flags that control what glyph information are serialized in <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" title="hb_buffer_serialize_glyphs ()"><code class="function">hb_buffer_serialize_glyphs()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-buffer-serialize-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-DEFAULT:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_DEFAULT</p></td>
+<td class="enum_member_description">
+<p>serialize glyph names, clusters and positions.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS</p></td>
+<td class="enum_member_description">
+<p>do not serialize glyph cluster.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS</p></td>
+<td class="enum_member_description">
+<p>do not serialize glyph position information.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES</p></td>
+<td class="enum_member_description">
+<p>do no serialize glyph name.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS</p></td>
+<td class="enum_member_description">
+<p>serialize glyph extents.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-GLYPH-FLAGS:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS</p></td>
+<td class="enum_member_description">
+<p>serialize glyph flags. Since: 1.5.0</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-SERIALIZE-FLAG-NO-ADVANCES:CAPS"></a>HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES</p></td>
+<td class="enum_member_description">
+<p>do not serialize glyph advances,
+ glyph offsets will reflect absolute glyph positions. Since: 1.8.0</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-20.html#api-index-0.9.20">0.9.20</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-buffer-diff-flags-t"></a><h3>enum hb_buffer_diff_flags_t</h3>
+<div class="refsect3">
+<a name="hb-buffer-diff-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-EQUAL:CAPS"></a>HB_BUFFER_DIFF_FLAG_EQUAL</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CONTENT-TYPE-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-LENGTH-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"></a>HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"></a>HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CODEPOINT-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-CLUSTER-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-GLYPH-FLAGS-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-BUFFER-DIFF-FLAG-POSITION-MISMATCH:CAPS"></a>HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 7db2c8b..7401836 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-common: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb.html" title="hb">
-<link rel="next" href="harfbuzz-hb-unicode.html" title="hb-unicode">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-buffer.html" title="hb-buffer">
+<link rel="next" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-common.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-unicode.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-buffer.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-deprecated.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-common"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-common.top_of_page"></a>hb-common</span></h2>
-<p>hb-common</p>
+<p>hb-common — Common data types</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-common.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_user_data_key_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">├──</span> hb_direction_t
     <span class="lineart">╰──</span> hb_script_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-common.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-common.description"></a><h2>Description</h2>
+<p>Common data types used across HarfBuzz are defined here.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-common.functions_details"></a><h2>Functions</h2>
@@ -394,7 +400,7 @@ corresponding <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="
 <tbody>
 <tr>
 <td class="parameter_name"><p>str</p></td>
-<td class="parameter_description"><p>a string representing an
+<td class="parameter_description"><p> a string representing an
 ISO 15924 tag. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
 </tr>
@@ -454,7 +460,7 @@ hb_script_get_horizontal_direction (<em class="parameter"><code><a class="link"
 hb_language_from_string (<em class="parameter"><code>const <span class="type">char</span> *str</code></em>,
                          <em class="parameter"><code><span class="type">int</span> len</code></em>);</pre>
 <p>Converts <em class="parameter"><code>str</code></em>
- representing an ISO 639 language code to the corresponding
+ representing a BCP 47 language tag to the corresponding
 <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a>.</p>
 <div class="refsect3">
 <a name="hb-language-from-string.parameters"></a><h4>Parameters</h4>
@@ -467,8 +473,8 @@ hb_language_from_string (<em class="parameter"><code>const <span class="type">ch
 <tbody>
 <tr>
 <td class="parameter_name"><p>str</p></td>
-<td class="parameter_description"><p>a string representing
-ISO 639 language code. </p></td>
+<td class="parameter_description"><p> a string representing
+a BCP 47 language tag. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
 </tr>
 <tr>
@@ -482,7 +488,7 @@ ISO 639 language code. </p></td>
 </div>
 <div class="refsect3">
 <a name="hb-language-from-string.returns"></a><h4>Returns</h4>
-<p>The <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> corresponding to the ISO 639 language code. </p>
+<p>The <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> corresponding to the BCP 47 language tag. </p>
 <p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
 </div>
 <p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
@@ -522,6 +528,13 @@ the caller. </p>
 <a name="hb-language-get-default"></a><h3>hb_language_get_default ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
 hb_language_get_default (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Get default language from current locale.</p>
+<p>Note that the first time this function is called, it calls
+"setlocale (LC_CTYPE, nullptr)" to fetch current locale.  The underlying
+setlocale function is, in many implementations, NOT threadsafe.  To avoid
+problems, call this function once before multiple threads can call it.
+This function is only used from <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-guess-segment-properties" title="hb_buffer_guess_segment_properties ()"><code class="function">hb_buffer_guess_segment_properties()</code></a> by
+HarfBuzz itself.</p>
 <div class="refsect3">
 <a name="hb-language-get-default.returns"></a><h4>Returns</h4>
 <p>. </p>
@@ -538,13 +551,13 @@ hb_language_get_default (<em class="parameter"><code><span class="type">void</sp
 <hr>
 <div class="refsect2">
 <a name="HB-TAG:CAPS"></a><h3>HB_TAG()</h3>
-<pre class="programlisting">#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))&lt;&lt;24)|(((uint8_t)(c2))&lt;&lt;16)|(((uint8_t)(c3))&lt;&lt;8)|((uint8_t)(c4))))
+<pre class="programlisting">#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&amp;0xFF)&lt;&lt;24)|(((uint32_t)(c2)&amp;0xFF)&lt;&lt;16)|(((uint32_t)(c3)&amp;0xFF)&lt;&lt;8)|((uint32_t)(c4)&amp;0xFF)))
 </pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="HB-UNTAG:CAPS"></a><h3>HB_UNTAG()</h3>
-<pre class="programlisting">#define HB_UNTAG(tag)   ((uint8_t)((tag)&gt;&gt;24)), ((uint8_t)((tag)&gt;&gt;16)), ((uint8_t)((tag)&gt;&gt;8)), ((uint8_t)(tag))
+<pre class="programlisting">#define HB_UNTAG(tag)   (uint8_t)(((tag)&gt;&gt;24)&amp;0xFF), (uint8_t)(((tag)&gt;&gt;16)&amp;0xFF), (uint8_t)(((tag)&gt;&gt;8)&amp;0xFF), (uint8_t)((tag)&amp;0xFF)
 </pre>
 </div>
 <hr>
@@ -685,22 +698,747 @@ hb_language_get_default (<em class="parameter"><code><span class="type">void</sp
 </colgroup>
 <tbody>
 <tr>
-<td class="enum_member_name"><p><a name="HB-SCRIPT-BASSA-VAH:CAPS"></a>HB_SCRIPT_BASSA_VAH</p></td>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-COMMON:CAPS"></a>HB_SCRIPT_COMMON</p></td>
 <td> </td>
 <td> </td>
 </tr>
 <tr>
-<td class="enum_member_name"><p><a name="HB-SCRIPT-ADLAM:CAPS"></a>HB_SCRIPT_ADLAM</p></td>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-INHERITED:CAPS"></a>HB_SCRIPT_INHERITED</p></td>
 <td> </td>
 <td> </td>
 </tr>
 <tr>
-<td class="enum_member_name"><p><a name="HB-SCRIPT-MASARAM-GONDI:CAPS"></a>HB_SCRIPT_MASARAM_GONDI</p></td>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-UNKNOWN:CAPS"></a>HB_SCRIPT_UNKNOWN</p></td>
 <td> </td>
 <td> </td>
 </tr>
 <tr>
-<td class="enum_member_name"><p><a name="HB-SCRIPT-DOGRA:CAPS"></a>HB_SCRIPT_DOGRA</p></td>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ARABIC:CAPS"></a>HB_SCRIPT_ARABIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ARMENIAN:CAPS"></a>HB_SCRIPT_ARMENIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BENGALI:CAPS"></a>HB_SCRIPT_BENGALI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CYRILLIC:CAPS"></a>HB_SCRIPT_CYRILLIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-DEVANAGARI:CAPS"></a>HB_SCRIPT_DEVANAGARI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GEORGIAN:CAPS"></a>HB_SCRIPT_GEORGIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GREEK:CAPS"></a>HB_SCRIPT_GREEK</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GUJARATI:CAPS"></a>HB_SCRIPT_GUJARATI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GURMUKHI:CAPS"></a>HB_SCRIPT_GURMUKHI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HANGUL:CAPS"></a>HB_SCRIPT_HANGUL</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HAN:CAPS"></a>HB_SCRIPT_HAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HEBREW:CAPS"></a>HB_SCRIPT_HEBREW</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HIRAGANA:CAPS"></a>HB_SCRIPT_HIRAGANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KANNADA:CAPS"></a>HB_SCRIPT_KANNADA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KATAKANA:CAPS"></a>HB_SCRIPT_KATAKANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LAO:CAPS"></a>HB_SCRIPT_LAO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LATIN:CAPS"></a>HB_SCRIPT_LATIN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MALAYALAM:CAPS"></a>HB_SCRIPT_MALAYALAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ORIYA:CAPS"></a>HB_SCRIPT_ORIYA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAMIL:CAPS"></a>HB_SCRIPT_TAMIL</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TELUGU:CAPS"></a>HB_SCRIPT_TELUGU</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-THAI:CAPS"></a>HB_SCRIPT_THAI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TIBETAN:CAPS"></a>HB_SCRIPT_TIBETAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BOPOMOFO:CAPS"></a>HB_SCRIPT_BOPOMOFO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BRAILLE:CAPS"></a>HB_SCRIPT_BRAILLE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CANADIAN-SYLLABICS:CAPS"></a>HB_SCRIPT_CANADIAN_SYLLABICS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CHEROKEE:CAPS"></a>HB_SCRIPT_CHEROKEE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ETHIOPIC:CAPS"></a>HB_SCRIPT_ETHIOPIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KHMER:CAPS"></a>HB_SCRIPT_KHMER</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MONGOLIAN:CAPS"></a>HB_SCRIPT_MONGOLIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MYANMAR:CAPS"></a>HB_SCRIPT_MYANMAR</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OGHAM:CAPS"></a>HB_SCRIPT_OGHAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-RUNIC:CAPS"></a>HB_SCRIPT_RUNIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SINHALA:CAPS"></a>HB_SCRIPT_SINHALA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SYRIAC:CAPS"></a>HB_SCRIPT_SYRIAC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-THAANA:CAPS"></a>HB_SCRIPT_THAANA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-YI:CAPS"></a>HB_SCRIPT_YI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-DESERET:CAPS"></a>HB_SCRIPT_DESERET</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GOTHIC:CAPS"></a>HB_SCRIPT_GOTHIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-ITALIC:CAPS"></a>HB_SCRIPT_OLD_ITALIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BUHID:CAPS"></a>HB_SCRIPT_BUHID</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HANUNOO:CAPS"></a>HB_SCRIPT_HANUNOO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAGALOG:CAPS"></a>HB_SCRIPT_TAGALOG</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAGBANWA:CAPS"></a>HB_SCRIPT_TAGBANWA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CYPRIOT:CAPS"></a>HB_SCRIPT_CYPRIOT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LIMBU:CAPS"></a>HB_SCRIPT_LIMBU</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LINEAR-B:CAPS"></a>HB_SCRIPT_LINEAR_B</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OSMANYA:CAPS"></a>HB_SCRIPT_OSMANYA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SHAVIAN:CAPS"></a>HB_SCRIPT_SHAVIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAI-LE:CAPS"></a>HB_SCRIPT_TAI_LE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-UGARITIC:CAPS"></a>HB_SCRIPT_UGARITIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BUGINESE:CAPS"></a>HB_SCRIPT_BUGINESE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-COPTIC:CAPS"></a>HB_SCRIPT_COPTIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GLAGOLITIC:CAPS"></a>HB_SCRIPT_GLAGOLITIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KHAROSHTHI:CAPS"></a>HB_SCRIPT_KHAROSHTHI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-NEW-TAI-LUE:CAPS"></a>HB_SCRIPT_NEW_TAI_LUE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-PERSIAN:CAPS"></a>HB_SCRIPT_OLD_PERSIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SYLOTI-NAGRI:CAPS"></a>HB_SCRIPT_SYLOTI_NAGRI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TIFINAGH:CAPS"></a>HB_SCRIPT_TIFINAGH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BALINESE:CAPS"></a>HB_SCRIPT_BALINESE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CUNEIFORM:CAPS"></a>HB_SCRIPT_CUNEIFORM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-NKO:CAPS"></a>HB_SCRIPT_NKO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PHAGS-PA:CAPS"></a>HB_SCRIPT_PHAGS_PA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PHOENICIAN:CAPS"></a>HB_SCRIPT_PHOENICIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CARIAN:CAPS"></a>HB_SCRIPT_CARIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CHAM:CAPS"></a>HB_SCRIPT_CHAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KAYAH-LI:CAPS"></a>HB_SCRIPT_KAYAH_LI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LEPCHA:CAPS"></a>HB_SCRIPT_LEPCHA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LYCIAN:CAPS"></a>HB_SCRIPT_LYCIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LYDIAN:CAPS"></a>HB_SCRIPT_LYDIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OL-CHIKI:CAPS"></a>HB_SCRIPT_OL_CHIKI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-REJANG:CAPS"></a>HB_SCRIPT_REJANG</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SAURASHTRA:CAPS"></a>HB_SCRIPT_SAURASHTRA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SUNDANESE:CAPS"></a>HB_SCRIPT_SUNDANESE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-VAI:CAPS"></a>HB_SCRIPT_VAI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-AVESTAN:CAPS"></a>HB_SCRIPT_AVESTAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BAMUM:CAPS"></a>HB_SCRIPT_BAMUM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-EGYPTIAN-HIEROGLYPHS:CAPS"></a>HB_SCRIPT_EGYPTIAN_HIEROGLYPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-IMPERIAL-ARAMAIC:CAPS"></a>HB_SCRIPT_IMPERIAL_ARAMAIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-INSCRIPTIONAL-PAHLAVI:CAPS"></a>HB_SCRIPT_INSCRIPTIONAL_PAHLAVI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-INSCRIPTIONAL-PARTHIAN:CAPS"></a>HB_SCRIPT_INSCRIPTIONAL_PARTHIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-JAVANESE:CAPS"></a>HB_SCRIPT_JAVANESE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KAITHI:CAPS"></a>HB_SCRIPT_KAITHI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LISU:CAPS"></a>HB_SCRIPT_LISU</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MEETEI-MAYEK:CAPS"></a>HB_SCRIPT_MEETEI_MAYEK</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-SOUTH-ARABIAN:CAPS"></a>HB_SCRIPT_OLD_SOUTH_ARABIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-TURKIC:CAPS"></a>HB_SCRIPT_OLD_TURKIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SAMARITAN:CAPS"></a>HB_SCRIPT_SAMARITAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAI-THAM:CAPS"></a>HB_SCRIPT_TAI_THAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAI-VIET:CAPS"></a>HB_SCRIPT_TAI_VIET</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BATAK:CAPS"></a>HB_SCRIPT_BATAK</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BRAHMI:CAPS"></a>HB_SCRIPT_BRAHMI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MANDAIC:CAPS"></a>HB_SCRIPT_MANDAIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CHAKMA:CAPS"></a>HB_SCRIPT_CHAKMA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MEROITIC-CURSIVE:CAPS"></a>HB_SCRIPT_MEROITIC_CURSIVE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MEROITIC-HIEROGLYPHS:CAPS"></a>HB_SCRIPT_MEROITIC_HIEROGLYPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MIAO:CAPS"></a>HB_SCRIPT_MIAO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SHARADA:CAPS"></a>HB_SCRIPT_SHARADA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SORA-SOMPENG:CAPS"></a>HB_SCRIPT_SORA_SOMPENG</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TAKRI:CAPS"></a>HB_SCRIPT_TAKRI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BASSA-VAH:CAPS"></a>HB_SCRIPT_BASSA_VAH</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-CAUCASIAN-ALBANIAN:CAPS"></a>HB_SCRIPT_CAUCASIAN_ALBANIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-DUPLOYAN:CAPS"></a>HB_SCRIPT_DUPLOYAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ELBASAN:CAPS"></a>HB_SCRIPT_ELBASAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GRANTHA:CAPS"></a>HB_SCRIPT_GRANTHA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KHOJKI:CAPS"></a>HB_SCRIPT_KHOJKI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-KHUDAWADI:CAPS"></a>HB_SCRIPT_KHUDAWADI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-LINEAR-A:CAPS"></a>HB_SCRIPT_LINEAR_A</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MAHAJANI:CAPS"></a>HB_SCRIPT_MAHAJANI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MANICHAEAN:CAPS"></a>HB_SCRIPT_MANICHAEAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MENDE-KIKAKUI:CAPS"></a>HB_SCRIPT_MENDE_KIKAKUI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MODI:CAPS"></a>HB_SCRIPT_MODI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MRO:CAPS"></a>HB_SCRIPT_MRO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-NABATAEAN:CAPS"></a>HB_SCRIPT_NABATAEAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-NORTH-ARABIAN:CAPS"></a>HB_SCRIPT_OLD_NORTH_ARABIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-PERMIC:CAPS"></a>HB_SCRIPT_OLD_PERMIC</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PAHAWH-HMONG:CAPS"></a>HB_SCRIPT_PAHAWH_HMONG</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PALMYRENE:CAPS"></a>HB_SCRIPT_PALMYRENE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PAU-CIN-HAU:CAPS"></a>HB_SCRIPT_PAU_CIN_HAU</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-PSALTER-PAHLAVI:CAPS"></a>HB_SCRIPT_PSALTER_PAHLAVI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SIDDHAM:CAPS"></a>HB_SCRIPT_SIDDHAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TIRHUTA:CAPS"></a>HB_SCRIPT_TIRHUTA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-WARANG-CITI:CAPS"></a>HB_SCRIPT_WARANG_CITI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-AHOM:CAPS"></a>HB_SCRIPT_AHOM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ANATOLIAN-HIEROGLYPHS:CAPS"></a>HB_SCRIPT_ANATOLIAN_HIEROGLYPHS</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HATRAN:CAPS"></a>HB_SCRIPT_HATRAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MULTANI:CAPS"></a>HB_SCRIPT_MULTANI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-HUNGARIAN:CAPS"></a>HB_SCRIPT_OLD_HUNGARIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SIGNWRITING:CAPS"></a>HB_SCRIPT_SIGNWRITING</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ADLAM:CAPS"></a>HB_SCRIPT_ADLAM</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-BHAIKSUKI:CAPS"></a>HB_SCRIPT_BHAIKSUKI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MARCHEN:CAPS"></a>HB_SCRIPT_MARCHEN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OSAGE:CAPS"></a>HB_SCRIPT_OSAGE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-TANGUT:CAPS"></a>HB_SCRIPT_TANGUT</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-NEWA:CAPS"></a>HB_SCRIPT_NEWA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MASARAM-GONDI:CAPS"></a>HB_SCRIPT_MASARAM_GONDI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-NUSHU:CAPS"></a>HB_SCRIPT_NUSHU</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SOYOMBO:CAPS"></a>HB_SCRIPT_SOYOMBO</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-ZANABAZAR-SQUARE:CAPS"></a>HB_SCRIPT_ZANABAZAR_SQUARE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-DOGRA:CAPS"></a>HB_SCRIPT_DOGRA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-GUNJALA-GONDI:CAPS"></a>HB_SCRIPT_GUNJALA_GONDI</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-HANIFI-ROHINGYA:CAPS"></a>HB_SCRIPT_HANIFI_ROHINGYA</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MAKASAR:CAPS"></a>HB_SCRIPT_MAKASAR</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-MEDEFAIDRIN:CAPS"></a>HB_SCRIPT_MEDEFAIDRIN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-OLD-SOGDIAN:CAPS"></a>HB_SCRIPT_OLD_SOGDIAN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-SCRIPT-SOGDIAN:CAPS"></a>HB_SCRIPT_SOGDIAN</p></td>
 <td> </td>
 <td> </td>
 </tr>
@@ -761,6 +1499,6 @@ hb_language_get_default (<em class="parameter"><code><span class="type">void</sp
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 24a7e11..fddeb85 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-coretext: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-uniscribe.html" title="hb-uniscribe">
-<link rel="next" href="harfbuzz-hb-gobject.html" title="hb-gobject">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="ch12.html" title="Integration API">
+<link rel="next" href="harfbuzz-hb-ft.html" title="hb-ft">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-coretext.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-uniscribe.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-gobject.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch12.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ft.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-coretext"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-coretext.top_of_page"></a>hb-coretext</span></h2>
-<p>hb-coretext</p>
+<p>hb-coretext — CoreText integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-coretext.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-coretext.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-coretext.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the CoreText fonts.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-coretext.functions_details"></a><h2>Functions</h2>
@@ -148,6 +154,6 @@ hb_coretext_font_get_ct_font (<em class="parameter"><code><a class="link" href="
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 60935e1..96ed0a1 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-deprecated: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-version.html" title="hb-version">
-<link rel="next" href="harfbuzz-hb-set.html" title="hb-set">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-common.html" title="hb-common">
+<link rel="next" href="harfbuzz-hb-face.html" title="hb-face">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-deprecated.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-version.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-set.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-common.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-face.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-deprecated"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-deprecated.top_of_page"></a>hb-deprecated</span></h2>
-<p>hb-deprecated</p>
+<p>hb-deprecated — Deprecated API</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <tbody>
 <tr>
 <td class="function_type">
-<span class="returnvalue">void</span>
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-func" title="hb_font_funcs_set_glyph_func ()">hb_font_funcs_set_glyph_func</a> <span class="c_punctuation">()</span>
+<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" title="hb_font_get_glyph_func_t ()">*hb_font_get_glyph_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
-<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" title="hb_font_get_glyph_func_t ()">*hb_font_get_glyph_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-ot-layout-table-find-script" title="hb_ot_layout_table_find_script ()">hb_ot_layout_table_find_script</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-deprecated.html#hb-set-invert" title="hb_set_invert ()">hb_set_invert</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-func-t" title="hb_font_get_glyph_kerning_func_t ()">*hb_font_get_glyph_kerning_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 </tbody>
 <td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="harfbuzz-hb-deprecated.html#HB-SCRIPT-CANADIAN-ABORIGINAL:CAPS" title="HB_SCRIPT_CANADIAN_ABORIGINAL">HB_SCRIPT_CANADIAN_ABORIGINAL</a></td>
 </tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-deprecated.html#HB-OT-VAR-NO-AXIS-INDEX:CAPS" title="HB_OT_VAR_NO_AXIS_INDEX">HB_OT_VAR_NO_AXIS_INDEX</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-deprecated.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" title="HB_UNICODE_MAX_DECOMPOSITION_LEN">HB_UNICODE_MAX_DECOMPOSITION_LEN</a></td>
+</tr>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t">hb_font_get_glyph_h_kerning_func_t</a></td>
+</tr>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t">hb_font_get_glyph_v_kerning_func_t</a></td>
+</tr>
 </tbody>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-deprecated.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-deprecated.description"></a><h2>Description</h2>
+<p>These API have been deprecated in favor of newer API, or because they
+were deemed unnecessary.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-deprecated.functions_details"></a><h2>Functions</h2>
 <div class="refsect2">
-<a name="hb-font-funcs-set-glyph-func"></a><h3>hb_font_funcs_set_glyph_func ()</h3>
+<a name="hb-font-get-glyph-func-t"></a><h3>hb_font_get_glyph_func_t ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+<span class="c_punctuation">(</span>*hb_font_get_glyph_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                             <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> unicode</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> variation_selector</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *glyph</code></em>,
+                             <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_func_t</code> is deprecated and should not be used in newly-written code.</p></div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-layout-table-find-script"></a><h3>hb_ot_layout_table_find_script ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_layout_table_find_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> script_tag</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> *script_index</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-funcs-set-glyph-h-kerning-func"></a><h3>hb_font_funcs_set_glyph_h_kerning_func ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
-hb_font_funcs_set_glyph_func (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
-                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" title="hb_font_get_glyph_func_t ()"><span class="type">hb_font_get_glyph_func_t</span></a> func</code></em>,
-                              <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
-                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
-<div class="warning"><p><code class="literal">hb_font_funcs_set_glyph_func</code> has been deprecated since version 1.2.3 and should not be used in newly-written code.</p></div>
-<p>Deprecated.  Use <a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyph-func" title="hb_font_funcs_set_nominal_glyph_func ()"><code class="function">hb_font_funcs_set_nominal_glyph_func()</code></a> and
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-variation-glyph-func" title="hb_font_funcs_set_variation_glyph_func ()"><code class="function">hb_font_funcs_set_variation_glyph_func()</code></a> instead.</p>
+hb_font_funcs_set_glyph_h_kerning_func
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t"><span class="type">hb_font_get_glyph_h_kerning_func_t</span></a> func</code></em>,
+                                <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_funcs_set_glyph_h_kerning_func</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
 <div class="refsect3">
-<a name="hb-font-funcs-set-glyph-func.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-funcs-set-glyph-h-kerning-func.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -130,24 +213,125 @@ hb_font_funcs_set_glyph_func (<em class="parameter"><code><a class="link" href="
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-func-t"></a><h3>hb_font_get_glyph_func_t ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-<span class="c_punctuation">(</span>*hb_font_get_glyph_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                             <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> unicode</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> variation_selector</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *glyph</code></em>,
-                             <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
-<div class="warning"><p><code class="literal">hb_font_get_glyph_func_t</code> is deprecated and should not be used in newly-written code.</p></div>
+<a name="hb-font-funcs-set-glyph-v-kerning-func"></a><h3>hb_font_funcs_set_glyph_v_kerning_func ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_font_funcs_set_glyph_v_kerning_func
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t"><span class="type">hb_font_get_glyph_v_kerning_func_t</span></a> func</code></em>,
+                                <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_funcs_set_glyph_v_kerning_func</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
+<div class="refsect3">
+<a name="hb-font-funcs-set-glyph-v-kerning-func.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>ffuncs</p></td>
+<td class="parameter_description"><p>font functions.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>func</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-set-invert"></a><h3>hb_set_invert ()</h3>
+<a name="hb-font-get-glyph-h-kerning"></a><h3>hb_font_get_glyph_h_kerning ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+hb_font_get_glyph_h_kerning (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> left_glyph</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> right_glyph</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_h_kerning</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
+<div class="refsect3">
+<a name="hb-font-get-glyph-h-kerning.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>a font.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-kerning-for-direction"></a><h3>hb_font_get_glyph_kerning_for_direction ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
-hb_set_invert (<em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *set</code></em>);</pre>
-<div class="warning"><p><code class="literal">hb_set_invert</code> has been deprecated since version 1.6.1 and should not be used in newly-written code.</p></div>
+hb_font_get_glyph_kerning_for_direction
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> first_glyph</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> second_glyph</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> direction</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *x</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *y</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_kerning_for_direction</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
+<div class="refsect3">
+<a name="hb-font-get-glyph-kerning-for-direction.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>a font.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>x</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>y</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-kerning-func-t"></a><h3>hb_font_get_glyph_kerning_func_t ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+<span class="c_punctuation">(</span>*hb_font_get_glyph_kerning_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                                     <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> first_glyph</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> second_glyph</code></em>,
+                                     <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_kerning_func_t</code> is deprecated and should not be used in newly-written code.</p></div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-v-kerning"></a><h3>hb_font_get_glyph_v_kerning ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+hb_font_get_glyph_v_kerning (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> top_glyph</code></em>,
+                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> bottom_glyph</code></em>);</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_v_kerning</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
 <div class="refsect3">
-<a name="hb-set-invert.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-get-glyph-v-kerning.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -155,13 +339,13 @@ hb_set_invert (<em class="parameter"><code><a class="link" href="harfbuzz-hb-set
 <col width="200px" class="parameters_annotations">
 </colgroup>
 <tbody><tr>
-<td class="parameter_name"><p>set</p></td>
-<td class="parameter_description"><p>a set.</p></td>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>a font.</p></td>
 <td class="parameter_annotations"> </td>
 </tr></tbody>
 </table></div>
 </div>
-<p class="since">Since: <a class="link" href="api-index-0-9-10.html#api-index-0.9.10">0.9.10</a></p>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
 </div>
 </div>
 <div class="refsect1">
@@ -186,9 +370,39 @@ hb_set_invert (<em class="parameter"><code><a class="link" href="harfbuzz-hb-set
 </pre>
 <div class="warning"><p><code class="literal">HB_SCRIPT_CANADIAN_ABORIGINAL</code> is deprecated and should not be used in newly-written code.</p></div>
 </div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-VAR-NO-AXIS-INDEX:CAPS"></a><h3>HB_OT_VAR_NO_AXIS_INDEX</h3>
+<pre class="programlisting">#define HB_OT_VAR_NO_AXIS_INDEX            0xFFFFFFFFu
+</pre>
+<div class="warning"><p><code class="literal">HB_OT_VAR_NO_AXIS_INDEX</code> has been deprecated since version 2.2.0 and should not be used in newly-written code.</p></div>
+<p class="since">Since: <a class="link" href="api-index-1-4-2.html#api-index-1.4.2">1.4.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS"></a><h3>HB_UNICODE_MAX_DECOMPOSITION_LEN</h3>
+<pre class="programlisting">#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
+</pre>
+<div class="warning"><p><code class="literal">HB_UNICODE_MAX_DECOMPOSITION_LEN</code> has been deprecated since version 2.0.0 and should not be used in newly-written code.</p></div>
+<p>See Unicode 6.1 for details on the maximum decomposition length.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-h-kerning-func-t"></a><h3>hb_font_get_glyph_h_kerning_func_t</h3>
+<pre class="programlisting">typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_h_kerning_func_t</code> is deprecated and should not be used in newly-written code.</p></div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-v-kerning-func-t"></a><h3>hb_font_get_glyph_v_kerning_func_t</h3>
+<pre class="programlisting">typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+</pre>
+<div class="warning"><p><code class="literal">hb_font_get_glyph_v_kerning_func_t</code> is deprecated and should not be used in newly-written code.</p></div>
+</div>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 7192ddc..25c817e 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-face: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-blob.html" title="hb-blob">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">
 <link rel="next" href="harfbuzz-hb-font.html" title="hb-font">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -19,8 +19,8 @@
                   <a href="#harfbuzz-hb-face.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-blob.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-deprecated.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="harfbuzz-hb-font.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
@@ -28,7 +28,7 @@
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-face.top_of_page"></a>hb-face</span></h2>
-<p>hb-face</p>
+<p>hb-face — Font face objects</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <a class="link" href="harfbuzz-hb-face.html#hb-face-set-user-data" title="hb_face_set_user_data ()">hb_face_set_user_data</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-unicodes" title="hb_face_collect_unicodes ()">hb_face_collect_unicodes</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-selectors" title="hb_face_collect_variation_selectors ()">hb_face_collect_variation_selectors</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-collect-variation-unicodes" title="hb_face_collect_variation_unicodes ()">hb_face_collect_variation_unicodes</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="returnvalue">hb_face_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-create" title="hb_face_builder_create ()">hb_face_builder_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-face.html#hb-face-builder-add-table" title="hb_face_builder_add_table ()">hb_face_builder_add_table</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
 </tbody>
 </table></div>
 </div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-face.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_face_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-face.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-face.description"></a><h2>Description</h2>
+<p>Font face is objects represent a single face in a font family.
+More exactly, a font face represents a single face in a binary font file.
+Font faces are typically built from a binary blob and a face index.
+Font faces are used to create fonts.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-face.functions_details"></a><h2>Functions</h2>
 <a name="hb-face-count"></a><h3>hb_face_count ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
 hb_face_count (<em class="parameter"><code><a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="type">hb_blob_t</span></a> *blob</code></em>);</pre>
+<p>Get number of faces in a blob.</p>
+<div class="refsect3">
+<a name="hb-face-count.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>blob</p></td>
+<td class="parameter_description"><p>a blob.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-face-count.returns"></a><h4>Returns</h4>
+<p> Number of faces in <em class="parameter"><code>blob</code></em>
+</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -299,7 +370,7 @@ hb_face_get_empty (<em class="parameter"><code><span class="type">void</span></c
 <div class="refsect2">
 <a name="hb-face-get-table-tags"></a><h3>hb_face_get_table_tags ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_face_get_table_tags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+hb_face_get_table_tags (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
                         <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
                         <em class="parameter"><code>unsigned <span class="type">int</span> *table_count</code></em>,
                         <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *table_tags</code></em>);</pre>
@@ -312,11 +383,29 @@ hb_face_get_table_tags (<em class="parameter"><code><a class="link" href="harfbu
 <col class="parameters_description">
 <col width="200px" class="parameters_annotations">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="parameter_name"><p>face</p></td>
 <td class="parameter_description"><p>a face.</p></td>
 <td class="parameter_annotations"> </td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="parameter_name"><p>start_offset</p></td>
+<td class="parameter_description"><p>index of first tag to return.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>table_count</p></td>
+<td class="parameter_description"><p>input length of <em class="parameter"><code>table_tags</code></em>
+array, output number of items written.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>table_tags</p></td>
+<td class="parameter_description"><p>array to write tags into.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
 </table></div>
 </div>
 <div class="refsect3">
@@ -329,7 +418,7 @@ hb_face_get_table_tags (<em class="parameter"><code><a class="link" href="harfbu
 <div class="refsect2">
 <a name="hb-face-get-glyph-count"></a><h3>hb_face_get_glyph_count ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_face_get_glyph_count (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+hb_face_get_glyph_count (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-face-get-glyph-count.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
@@ -351,7 +440,7 @@ hb_face_get_glyph_count (<em class="parameter"><code><a class="link" href="harfb
 <div class="refsect2">
 <a name="hb-face-get-index"></a><h3>hb_face_get_index ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_face_get_index (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+hb_face_get_index (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-face-get-index.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
@@ -373,7 +462,7 @@ hb_face_get_index (<em class="parameter"><code><a class="link" href="harfbuzz-hb
 <div class="refsect2">
 <a name="hb-face-get-upem"></a><h3>hb_face_get_upem ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_face_get_upem (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+hb_face_get_upem (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-face-get-upem.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
@@ -395,7 +484,7 @@ hb_face_get_upem (<em class="parameter"><code><a class="link" href="harfbuzz-hb-
 <div class="refsect2">
 <a name="hb-face-get-user-data"></a><h3>hb_face_get_user_data ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span> *
-hb_face_get_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+hb_face_get_user_data (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>);</pre>
 <p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
 <div class="refsect3">
@@ -424,7 +513,7 @@ hb_face_get_user_data (<em class="parameter"><code><a class="link" href="harfbuz
 <div class="refsect2">
 <a name="hb-face-is-immutable"></a><h3>hb_face_is_immutable ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_face_is_immutable (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+hb_face_is_immutable (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-face-is-immutable.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
@@ -518,7 +607,7 @@ hb_face_reference_blob (<em class="parameter"><code><a class="link" href="harfbu
 <div class="refsect2">
 <a name="hb-face-reference-table"></a><h3>hb_face_reference_table ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="returnvalue">hb_blob_t</span></a> *
-hb_face_reference_table (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+hb_face_reference_table (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
                          <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-face-reference-table.parameters"></a><h4>Parameters</h4>
@@ -638,6 +727,130 @@ hb_face_set_user_data (<em class="parameter"><code><a class="link" href="harfbuz
 </div>
 <p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
 </div>
+<hr>
+<div class="refsect2">
+<a name="hb-face-collect-unicodes"></a><h3>hb_face_collect_unicodes ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_face_collect_unicodes (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                          <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *out</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-face-collect-unicodes.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>out</p></td>
+<td class="parameter_description"><p>set to add Unicode characters covered by <em class="parameter"><code>face</code></em>
+to.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-face-collect-variation-selectors"></a><h3>hb_face_collect_variation_selectors ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_face_collect_variation_selectors (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *out</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-face-collect-variation-selectors.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>out</p></td>
+<td class="parameter_description"><p>set to add Variation Selector characters covered by <em class="parameter"><code>face</code></em>
+to.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-face-collect-variation-unicodes"></a><h3>hb_face_collect_variation_unicodes ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_face_collect_variation_unicodes (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                    <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> variation_selector</code></em>,
+                                    <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *out</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-face-collect-variation-unicodes.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>out</p></td>
+<td class="parameter_description"><p>set to add Unicode characters for <em class="parameter"><code>variation_selector</code></em>
+covered by <em class="parameter"><code>face</code></em>
+to.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-face-builder-create"></a><h3>hb_face_builder_create ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="returnvalue">hb_face_t</span></a> *
+hb_face_builder_create (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Creates a <a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> that can be used with <a class="link" href="harfbuzz-hb-face.html#hb-face-builder-add-table" title="hb_face_builder_add_table ()"><code class="function">hb_face_builder_add_table()</code></a>.
+After tables are added to the face, it can be compiled to a binary
+font file by calling <a class="link" href="harfbuzz-hb-face.html#hb-face-reference-blob" title="hb_face_reference_blob ()"><code class="function">hb_face_reference_blob()</code></a>.</p>
+<div class="refsect3">
+<a name="hb-face-builder-create.returns"></a><h4>Returns</h4>
+<p> New face. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-face-builder-add-table"></a><h3>hb_face_builder_add_table ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_face_builder_add_table (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                           <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>,
+                           <em class="parameter"><code><a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="type">hb_blob_t</span></a> *blob</code></em>);</pre>
+<p>Add table for <em class="parameter"><code>tag</code></em>
+ with data provided by <em class="parameter"><code>blob</code></em>
+ to the face.  <em class="parameter"><code>face</code></em>
+ must
+be created using <a class="link" href="harfbuzz-hb-face.html#hb-face-builder-create" title="hb_face_builder_create ()"><code class="function">hb_face_builder_create()</code></a>.</p>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
+</div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-face.other_details"></a><h2>Types and Values</h2>
@@ -649,6 +862,6 @@ hb_face_set_user_data (<em class="parameter"><code><a class="link" href="harfbuz
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 21e08e2..10c7d9e 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-font: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
+<link rel="up" href="ch09.html" title="Core API">
 <link rel="prev" href="harfbuzz-hb-face.html" title="hb-face">
-<link rel="next" href="harfbuzz-Shaping.html" title="Shaping">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="harfbuzz-hb-map.html" title="hb-map">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-font.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
 <td><a accesskey="p" href="harfbuzz-hb-face.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-Shaping.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-map.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-font"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-font.top_of_page"></a>hb-font</span></h2>
-<p>hb-font</p>
+<p>hb-font — Font objects</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-kerning-func" title="hb_font_funcs_set_glyph_h_kerning_func ()">hb_font_funcs_set_glyph_h_kerning_func</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advances-func" title="hb_font_funcs_set_glyph_h_advances_func ()">hb_font_funcs_set_glyph_h_advances_func</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-kerning-func" title="hb_font_funcs_set_glyph_v_kerning_func ()">hb_font_funcs_set_glyph_v_kerning_func</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advances-func" title="hb_font_funcs_set_glyph_v_advances_func ()">hb_font_funcs_set_glyph_v_advances_func</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 </tr>
 <tr>
 <td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyphs-func" title="hb_font_funcs_set_nominal_glyphs_func ()">hb_font_funcs_set_nominal_glyphs_func</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
 </tr>
 <tr>
 <td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advances-for-direction" title="hb_font_get_glyph_advances_for_direction ()">hb_font_get_glyph_advances_for_direction</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-advances-func-t" title="hb_font_get_glyph_advances_func_t ()">*hb_font_get_glyph_advances_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
 </tr>
 <tr>
 <td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+<span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning" title="hb_font_get_glyph_h_kerning ()">hb_font_get_glyph_h_kerning</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances" title="hb_font_get_glyph_h_advances ()">hb_font_get_glyph_h_advances</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 </tr>
 <tr>
 <td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-for-direction" title="hb_font_get_glyph_kerning_for_direction ()">hb_font_get_glyph_kerning_for_direction</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
-</td>
-<td class="function_name">
-<span class="c_punctuation">(</span><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-func-t" title="hb_font_get_glyph_kerning_func_t ()">*hb_font_get_glyph_kerning_func_t</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
 </tr>
 <tr>
 <td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
+<span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning" title="hb_font_get_glyph_v_kerning ()">hb_font_get_glyph_v_kerning</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances" title="hb_font_get_glyph_v_advances ()">hb_font_get_glyph_v_advances</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 </tr>
 <tr>
 <td class="typedef_keyword">typedef</td>
-<td class="function_name"><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t">hb_font_get_glyph_h_kerning_func_t</a></td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances-func-t" title="hb_font_get_glyph_h_advances_func_t">hb_font_get_glyph_h_advances_func_t</a></td>
 </tr>
 <tr>
 <td class="typedef_keyword">typedef</td>
 </tr>
 <tr>
 <td class="typedef_keyword">typedef</td>
-<td class="function_name"><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t">hb_font_get_glyph_v_kerning_func_t</a></td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances-func-t" title="hb_font_get_glyph_v_advances_func_t">hb_font_get_glyph_v_advances_func_t</a></td>
 </tr>
 <tr>
 <td class="typedef_keyword">typedef</td>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-font.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">├──</span> hb_font_funcs_t
     <span class="lineart">╰──</span> hb_font_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-font.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-font.description"></a><h2>Description</h2>
+<p>Font objects represent a font face at a certain size and other
+parameters (pixels per EM, points per EM, variation settings.)
+Fonts are created from font faces, and are used as input to
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a> among other things.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-font.functions_details"></a><h2>Functions</h2>
@@ -1182,15 +1199,15 @@ hb_font_funcs_set_glyph_h_advance_func
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-funcs-set-glyph-h-kerning-func"></a><h3>hb_font_funcs_set_glyph_h_kerning_func ()</h3>
+<a name="hb-font-funcs-set-glyph-h-advances-func"></a><h3>hb_font_funcs_set_glyph_h_advances_func ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
-hb_font_funcs_set_glyph_h_kerning_func
+hb_font_funcs_set_glyph_h_advances_func
                                (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning-func-t" title="hb_font_get_glyph_h_kerning_func_t"><span class="type">hb_font_get_glyph_h_kerning_func_t</span></a> func</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances-func-t" title="hb_font_get_glyph_h_advances_func_t"><span class="type">hb_font_get_glyph_h_advances_func_t</span></a> func</code></em>,
                                 <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
 <div class="refsect3">
-<a name="hb-font-funcs-set-glyph-h-kerning-func.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-funcs-set-glyph-h-advances-func.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -1211,7 +1228,7 @@ hb_font_funcs_set_glyph_h_kerning_func
 </tbody>
 </table></div>
 </div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+<p class="since">Since: <a class="link" href="api-index-1-8-6.html#api-index-1.8.6">1.8.6</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -1312,15 +1329,15 @@ hb_font_funcs_set_glyph_v_advance_func
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-funcs-set-glyph-v-kerning-func"></a><h3>hb_font_funcs_set_glyph_v_kerning_func ()</h3>
+<a name="hb-font-funcs-set-glyph-v-advances-func"></a><h3>hb_font_funcs_set_glyph_v_advances_func ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
-hb_font_funcs_set_glyph_v_kerning_func
+hb_font_funcs_set_glyph_v_advances_func
                                (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning-func-t" title="hb_font_get_glyph_v_kerning_func_t"><span class="type">hb_font_get_glyph_v_kerning_func_t</span></a> func</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances-func-t" title="hb_font_get_glyph_v_advances_func_t"><span class="type">hb_font_get_glyph_v_advances_func_t</span></a> func</code></em>,
                                 <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
 <div class="refsect3">
-<a name="hb-font-funcs-set-glyph-v-kerning-func.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-funcs-set-glyph-v-advances-func.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -1341,7 +1358,7 @@ hb_font_funcs_set_glyph_v_kerning_func
 </tbody>
 </table></div>
 </div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+<p class="since">Since: <a class="link" href="api-index-1-8-6.html#api-index-1.8.6">1.8.6</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -1409,6 +1426,38 @@ hb_font_funcs_set_nominal_glyph_func (<em class="parameter"><code><a class="link
 </div>
 <hr>
 <div class="refsect2">
+<a name="hb-font-funcs-set-nominal-glyphs-func"></a><h3>hb_font_funcs_set_nominal_glyphs_func ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_font_funcs_set_nominal_glyphs_func (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
+                                       <em class="parameter"><code><span class="type">hb_font_get_nominal_glyphs_func_t</span> func</code></em>,
+                                       <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
+                                       <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-font-funcs-set-nominal-glyphs-func.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>ffuncs</p></td>
+<td class="parameter_description"><p>font functions.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>func</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-font-funcs-set-user-data"></a><h3>hb_font_funcs_set_user_data ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 hb_font_funcs_set_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t"><span class="type">hb_font_funcs_t</span></a> *ffuncs</code></em>,
@@ -1587,6 +1636,48 @@ hb_font_get_glyph_advance_for_direction
 </div>
 <hr>
 <div class="refsect2">
+<a name="hb-font-get-glyph-advances-for-direction"></a><h3>hb_font_get_glyph_advances_for_direction ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_font_get_glyph_advances_for_direction
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> direction</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> count</code></em>,
+                                <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *first_glyph</code></em>,
+                                <em class="parameter"><code><span class="type">unsigned </span> glyph_stride</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *first_advance</code></em>,
+                                <em class="parameter"><code><span class="type">unsigned </span> advance_stride</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-font-get-glyph-advances-for-direction.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>a font.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-8-6.html#api-index-1.8.6">1.8.6</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-font-get-glyph-advances-func-t"></a><h3>hb_font_get_glyph_advances_func_t ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+<span class="c_punctuation">(</span>*hb_font_get_glyph_advances_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                                      <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
+                                      <em class="parameter"><code>unsigned <span class="type">int</span> count</code></em>,
+                                      <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *first_glyph</code></em>,
+                                      <em class="parameter"><code><span class="type">unsigned </span> glyph_stride</code></em>,
+                                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *first_advance</code></em>,
+                                      <em class="parameter"><code><span class="type">unsigned </span> advance_stride</code></em>,
+                                      <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-font-get-glyph-contour-point"></a><h3>hb_font_get_glyph_contour_point ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 hb_font_get_glyph_contour_point (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
@@ -1820,13 +1911,16 @@ hb_font_get_glyph_h_advance (<em class="parameter"><code><a class="link" href="h
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-h-kerning"></a><h3>hb_font_get_glyph_h_kerning ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
-hb_font_get_glyph_h_kerning (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> left_glyph</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> right_glyph</code></em>);</pre>
+<a name="hb-font-get-glyph-h-advances"></a><h3>hb_font_get_glyph_h_advances ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_font_get_glyph_h_advances (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                              <em class="parameter"><code>unsigned <span class="type">int</span> count</code></em>,
+                              <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *first_glyph</code></em>,
+                              <em class="parameter"><code><span class="type">unsigned </span> glyph_stride</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *first_advance</code></em>,
+                              <em class="parameter"><code><span class="type">unsigned </span> advance_stride</code></em>);</pre>
 <div class="refsect3">
-<a name="hb-font-get-glyph-h-kerning.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-get-glyph-h-advances.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -1840,7 +1934,7 @@ hb_font_get_glyph_h_kerning (<em class="parameter"><code><a class="link" href="h
 </tr></tbody>
 </table></div>
 </div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+<p class="since">Since: <a class="link" href="api-index-1-8-6.html#api-index-1.8.6">1.8.6</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -1881,56 +1975,6 @@ hb_font_get_glyph_h_origin (<em class="parameter"><code><a class="link" href="ha
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-kerning-for-direction"></a><h3>hb_font_get_glyph_kerning_for_direction ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_font_get_glyph_kerning_for_direction
-                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> first_glyph</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> second_glyph</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t"><span class="type">hb_direction_t</span></a> direction</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *x</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *y</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-font-get-glyph-kerning-for-direction.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>font</p></td>
-<td class="parameter_description"><p>a font.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>x</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-<tr>
-<td class="parameter_name"><p>y</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-font-get-glyph-kerning-func-t"></a><h3>hb_font_get_glyph_kerning_func_t ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
-<span class="c_punctuation">(</span>*hb_font_get_glyph_kerning_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                                     <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
-                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> first_glyph</code></em>,
-                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> second_glyph</code></em>,
-                                     <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-font-get-glyph-name"></a><h3>hb_font_get_glyph_name ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 hb_font_get_glyph_name (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
@@ -2047,13 +2091,16 @@ hb_font_get_glyph_v_advance (<em class="parameter"><code><a class="link" href="h
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-v-kerning"></a><h3>hb_font_get_glyph_v_kerning ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="returnvalue">hb_position_t</span></a>
-hb_font_get_glyph_v_kerning (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> top_glyph</code></em>,
-                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> bottom_glyph</code></em>);</pre>
+<a name="hb-font-get-glyph-v-advances"></a><h3>hb_font_get_glyph_v_advances ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_font_get_glyph_v_advances (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                              <em class="parameter"><code>unsigned <span class="type">int</span> count</code></em>,
+                              <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *first_glyph</code></em>,
+                              <em class="parameter"><code><span class="type">unsigned </span> glyph_stride</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-position-t" title="hb_position_t"><span class="type">hb_position_t</span></a> *first_advance</code></em>,
+                              <em class="parameter"><code><span class="type">unsigned </span> advance_stride</code></em>);</pre>
 <div class="refsect3">
-<a name="hb-font-get-glyph-v-kerning.parameters"></a><h4>Parameters</h4>
+<a name="hb-font-get-glyph-v-advances.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
 <colgroup>
 <col width="150px" class="parameters_name">
@@ -2067,7 +2114,7 @@ hb_font_get_glyph_v_kerning (<em class="parameter"><code><a class="link" href="h
 </tr></tbody>
 </table></div>
 </div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+<p class="since">Since: <a class="link" href="api-index-1-8-6.html#api-index-1.8.6">1.8.6</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -2653,7 +2700,8 @@ hb_font_set_ppem (<em class="parameter"><code><a class="link" href="harfbuzz-hb-
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_font_set_ptem (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
                   <em class="parameter"><code><span class="type">float</span> ptem</code></em>);</pre>
-<p>Sets "point size" of the font.</p>
+<p>Sets "point size" of the font.  Set to 0 to unset.</p>
+<p>There are 72 points in an inch.</p>
 <div class="refsect3">
 <a name="hb-font-set-ptem.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" border="0">
@@ -2662,11 +2710,18 @@ hb_font_set_ptem (<em class="parameter"><code><a class="link" href="harfbuzz-hb-
 <col class="parameters_description">
 <col width="200px" class="parameters_annotations">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="parameter_name"><p>font</p></td>
 <td class="parameter_description"><p>a font.</p></td>
 <td class="parameter_annotations"> </td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="parameter_name"><p>ptem</p></td>
+<td class="parameter_description"><p>font size in points.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
 </table></div>
 </div>
 <p class="since">Since: <a class="link" href="api-index-1-6-0.html#api-index-1.6.0">1.6.0</a></p>
@@ -2893,11 +2948,18 @@ hb_font_get_extents_for_direction (<em class="parameter"><code><a class="link" h
 <col class="parameters_description">
 <col width="200px" class="parameters_annotations">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="parameter_name"><p>font</p></td>
 <td class="parameter_description"><p>a font.</p></td>
 <td class="parameter_annotations"> </td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="parameter_name"><p>extents</p></td>
+<td class="parameter_description"><p>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
 </table></div>
 </div>
 <p class="since">Since: <a class="link" href="api-index-1-1-3.html#api-index-1.1.3">1.1.3</a></p>
@@ -2908,7 +2970,7 @@ hb_font_get_extents_for_direction (<em class="parameter"><code><a class="link" h
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 <span class="c_punctuation">(</span>*hb_font_get_font_extents_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
                                     <em class="parameter"><code><span class="type">void</span> *font_data</code></em>,
-                                    <em class="parameter"><code><span class="type">hb_font_extents_t</span> *metrics</code></em>,
+                                    <em class="parameter"><code><span class="type">hb_font_extents_t</span> *extents</code></em>,
                                     <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
 </div>
 <hr>
@@ -2987,8 +3049,8 @@ hb_font_get_v_extents (<em class="parameter"><code><a class="link" href="harfbuz
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-h-kerning-func-t"></a><h3>hb_font_get_glyph_h_kerning_func_t</h3>
-<pre class="programlisting">typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+<a name="hb-font-get-glyph-h-advances-func-t"></a><h3>hb_font_get_glyph_h_advances_func_t</h3>
+<pre class="programlisting">typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
 </pre>
 </div>
 <hr>
@@ -3005,8 +3067,8 @@ hb_font_get_v_extents (<em class="parameter"><code><a class="link" href="harfbuz
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-font-get-glyph-v-kerning-func-t"></a><h3>hb_font_get_glyph_v_kerning_func_t</h3>
-<pre class="programlisting">typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+<a name="hb-font-get-glyph-v-advances-func-t"></a><h3>hb_font_get_glyph_v_advances_func_t</h3>
+<pre class="programlisting">typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
 </pre>
 </div>
 <hr>
@@ -3046,6 +3108,6 @@ hb_font_get_v_extents (<em class="parameter"><code><a class="link" href="harfbuz
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index c2ad492..79f3331 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-ft: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-icu.html" title="hb-icu">
-<link rel="next" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-coretext.html" title="hb-coretext">
+<link rel="next" href="harfbuzz-hb-glib.html" title="hb-glib">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-ft.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-icu.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-graphite2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-coretext.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-glib.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-ft"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-ft.top_of_page"></a>hb-ft</span></h2>
-<p>hb-ft</p>
+<p>hb-ft — FreeType integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-ft.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ft.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-ft.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the FreeType library to provide face and
+font data.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ft.functions_details"></a><h2>Functions</h2>
@@ -257,6 +264,6 @@ hb_ft_font_set_funcs (<em class="parameter"><code><a class="link" href="harfbuzz
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 5db6131..b4f56a4 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-glib: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-shape-plan.html" title="hb-shape-plan">
-<link rel="next" href="harfbuzz-hb-icu.html" title="hb-icu">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-ft.html" title="hb-ft">
+<link rel="next" href="harfbuzz-hb-gobject.html" title="hb-gobject">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-glib.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-shape-plan.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-icu.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ft.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-gobject.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-glib"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-glib.top_of_page"></a>hb-glib</span></h2>
-<p>hb-glib</p>
+<p>hb-glib — GLib integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-glib.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-glib.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-glib.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the GLib library to provide Unicode data.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-glib.functions_details"></a><h2>Functions</h2>
@@ -109,6 +115,6 @@ hb_glib_blob_create (<em class="parameter"><code><span class="type">GBytes</span
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index e42ad96..9e1a2a1 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-gobject: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-coretext.html" title="hb-coretext">
-<link rel="next" href="object-tree.html" title="Object Hierarchy">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-glib.html" title="hb-glib">
+<link rel="next" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-gobject.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-coretext.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="object-tree.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-glib.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-graphite2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-gobject"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-gobject.top_of_page"></a>hb-gobject</span></h2>
-<p>hb-gobject</p>
+<p>hb-gobject — GObject integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <span class="returnvalue">GType</span>
 </td>
 <td class="function_name">
+<a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-map-get-type" title="hb_gobject_map_get_type ()">hb_gobject_map_get_type</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">GType</span>
+</td>
+<td class="function_name">
 <a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-memory-mode-get-type" title="hb_gobject_memory_mode_get_type ()">hb_gobject_memory_mode_get_type</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <span class="returnvalue">GType</span>
 </td>
 <td class="function_name">
+<a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-ot-color-palette-flags-get-type" title="hb_gobject_ot_color_palette_flags_get_type ()">hb_gobject_ot_color_palette_flags_get_type</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">GType</span>
+</td>
+<td class="function_name">
 <a class="link" href="harfbuzz-hb-gobject.html#hb-gobject-ot-layout-glyph-class-get-type" title="hb_gobject_ot_layout_glyph_class_get_type ()">hb_gobject_ot_layout_glyph_class_get_type</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 </tr>
 <tr>
 <td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MAP:CAPS" title="HB_GOBJECT_TYPE_MAP">HB_GOBJECT_TYPE_MAP</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MEMORY-MODE:CAPS" title="HB_GOBJECT_TYPE_MEMORY_MODE">HB_GOBJECT_TYPE_MEMORY_MODE</a></td>
 </tr>
 <tr>
 <td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-COLOR-PALETTE-FLAGS:CAPS" title="HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS">HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-LAYOUT-GLYPH-CLASS:CAPS" title="HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS">HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS</a></td>
 </tr>
 <tr>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-gobject.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-gobject.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-gobject.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the GObject library to provide
+type data.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-gobject.functions_details"></a><h2>Functions</h2>
@@ -441,19 +472,19 @@ hb_gobject_blob_get_type (<em class="parameter"><code><span class="type">void</s
 <a name="hb-gobject-buffer-content-type-get-type"></a><h3>hb_gobject_buffer_content_type_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_buffer_content_type_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-buffer-diff-flags-get-type"></a><h3>hb_gobject_buffer_diff_flags_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_buffer_diff_flags_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_buffer_diff_flags_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-buffer-flags-get-type"></a><h3>hb_gobject_buffer_flags_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_buffer_flags_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_buffer_flags_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -467,20 +498,20 @@ hb_gobject_buffer_get_type (<em class="parameter"><code><span class="type">void<
 <a name="hb-gobject-buffer-serialize-flags-get-type"></a><h3>hb_gobject_buffer_serialize_flags_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_buffer_serialize_flags_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-buffer-serialize-format-get-type"></a><h3>hb_gobject_buffer_serialize_format_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_buffer_serialize_format_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-direction-get-type"></a><h3>hb_gobject_direction_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_direction_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_direction_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -507,26 +538,39 @@ hb_gobject_font_get_type (<em class="parameter"><code><span class="type">void</s
 <div class="refsect2">
 <a name="hb-gobject-glyph-flags-get-type"></a><h3>hb_gobject_glyph_flags_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_glyph_flags_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_glyph_flags_get_type ();</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-gobject-map-get-type"></a><h3>hb_gobject_map_get_type ()</h3>
+<pre class="programlisting"><span class="returnvalue">GType</span>
+hb_gobject_map_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-memory-mode-get-type"></a><h3>hb_gobject_memory_mode_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_memory_mode_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_memory_mode_get_type ();</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-gobject-ot-color-palette-flags-get-type"></a><h3>hb_gobject_ot_color_palette_flags_get_type ()</h3>
+<pre class="programlisting"><span class="returnvalue">GType</span>
+hb_gobject_ot_color_palette_flags_get_type
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-ot-layout-glyph-class-get-type"></a><h3>hb_gobject_ot_layout_glyph_class_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_ot_layout_glyph_class_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-ot-math-constant-get-type"></a><h3>hb_gobject_ot_math_constant_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_ot_math_constant_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_ot_math_constant_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -540,7 +584,7 @@ hb_gobject_ot_math_glyph_part_get_type
 <a name="hb-gobject-ot-math-glyph-part-flags-get-type"></a><h3>hb_gobject_ot_math_glyph_part_flags_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_ot_math_glyph_part_flags_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -553,13 +597,13 @@ hb_gobject_ot_math_glyph_variant_get_type
 <div class="refsect2">
 <a name="hb-gobject-ot-math-kern-get-type"></a><h3>hb_gobject_ot_math_kern_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_ot_math_kern_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_ot_math_kern_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-script-get-type"></a><h3>hb_gobject_script_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
-hb_gobject_script_get_type (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+hb_gobject_script_get_type ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -572,7 +616,7 @@ hb_gobject_shape_plan_get_type (<em class="parameter"><code><span class="type">v
 <a name="hb-gobject-unicode-combining-class-get-type"></a><h3>hb_gobject_unicode_combining_class_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_unicode_combining_class_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -586,14 +630,14 @@ hb_gobject_unicode_funcs_get_type (<em class="parameter"><code><span class="type
 <a name="hb-gobject-unicode-general-category-get-type"></a><h3>hb_gobject_unicode_general_category_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_unicode_general_category_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="hb-gobject-buffer-cluster-level-get-type"></a><h3>hb_gobject_buffer_cluster_level_get_type ()</h3>
 <pre class="programlisting"><span class="returnvalue">GType</span>
 hb_gobject_buffer_cluster_level_get_type
-                               (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+                               ();</pre>
 </div>
 <hr>
 <div class="refsect2">
@@ -708,12 +752,24 @@ hb_gobject_user_data_key_get_type (<em class="parameter"><code><span class="type
 </div>
 <hr>
 <div class="refsect2">
+<a name="HB-GOBJECT-TYPE-MAP:CAPS"></a><h3>HB_GOBJECT_TYPE_MAP</h3>
+<pre class="programlisting">#define HB_GOBJECT_TYPE_MAP (hb_gobject_map_get_type ())
+</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="HB-GOBJECT-TYPE-MEMORY-MODE:CAPS"></a><h3>HB_GOBJECT_TYPE_MEMORY_MODE</h3>
 <pre class="programlisting">#define HB_GOBJECT_TYPE_MEMORY_MODE (hb_gobject_memory_mode_get_type ())
 </pre>
 </div>
 <hr>
 <div class="refsect2">
+<a name="HB-GOBJECT-TYPE-OT-COLOR-PALETTE-FLAGS:CAPS"></a><h3>HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS</h3>
+<pre class="programlisting">#define HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS (hb_gobject_ot_color_palette_flags_get_type ())
+</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="HB-GOBJECT-TYPE-OT-LAYOUT-GLYPH-CLASS:CAPS"></a><h3>HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS</h3>
 <pre class="programlisting">#define HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS (hb_gobject_ot_layout_glyph_class_get_type ())
 </pre>
@@ -823,6 +879,6 @@ hb_gobject_user_data_key_get_type (<em class="parameter"><code><span class="type
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 88904e5..2fdd621 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-graphite2: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ft.html" title="hb-ft">
-<link rel="next" href="harfbuzz-hb-uniscribe.html" title="hb-uniscribe">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-gobject.html" title="hb-gobject">
+<link rel="next" href="harfbuzz-hb-icu.html" title="hb-icu">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-graphite2.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ft.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-uniscribe.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-gobject.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-icu.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-graphite2"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-graphite2.top_of_page"></a>hb-graphite2</span></h2>
-<p>hb-graphite2</p>
+<p>hb-graphite2 — Graphite2 integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <col width="150px" class="functions_return">
 <col class="functions_name">
 </colgroup>
-<tbody>
-<tr>
+<tbody><tr>
 <td class="function_type">
 <span class="returnvalue">gr_face</span> *
 </td>
 <td class="function_name">
 <a class="link" href="harfbuzz-hb-graphite2.html#hb-graphite2-face-get-gr-face" title="hb_graphite2_face_get_gr_face ()">hb_graphite2_face_get_gr_face</a> <span class="c_punctuation">()</span>
 </td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">gr_font</span> *
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-graphite2.html#hb-graphite2-font-get-gr-font" title="hb_graphite2_font_get_gr_font ()">hb_graphite2_font_get_gr_font</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-</tbody>
+</tr></tbody>
 </table></div>
 </div>
 <div class="refsect1">
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-graphite2.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-graphite2.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-graphite2.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the Graphite2 fonts.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-graphite2.functions_details"></a><h2>Functions</h2>
 <pre class="programlisting"><span class="returnvalue">gr_face</span> *
 hb_graphite2_face_get_gr_face (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
 </div>
-<hr>
-<div class="refsect2">
-<a name="hb-graphite2-font-get-gr-font"></a><h3>hb_graphite2_font_get_gr_font ()</h3>
-<pre class="programlisting"><span class="returnvalue">gr_font</span> *
-hb_graphite2_font_get_gr_font (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>);</pre>
-<div class="warning"><p><code class="literal">hb_graphite2_font_get_gr_font</code> is deprecated and should not be used in newly-written code.</p></div>
-</div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-graphite2.other_details"></a><h2>Types and Values</h2>
@@ -99,6 +88,6 @@ hb_graphite2_font_get_gr_font (<em class="parameter"><code><a class="link" href=
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 25a5cd6..68fa6aa 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-icu: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-glib.html" title="hb-glib">
-<link rel="next" href="harfbuzz-hb-ft.html" title="hb-ft">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">
+<link rel="next" href="harfbuzz-hb-uniscribe.html" title="hb-uniscribe">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-icu.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-glib.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ft.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-graphite2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-uniscribe.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-icu"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-icu.top_of_page"></a>hb-icu</span></h2>
-<p>hb-icu</p>
+<p>hb-icu — ICU integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-icu.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-icu.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-icu.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the ICU library to provide Unicode data.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-icu.functions_details"></a><h2>Functions</h2>
@@ -94,6 +100,6 @@ hb_icu_script_to_script (<em class="parameter"><code><span class="type">UScriptC
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-map.html b/docs/html/harfbuzz-hb-map.html
new file mode 100644 (file)
index 0000000..d5f0e4b
--- /dev/null
@@ -0,0 +1,526 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-map: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-font.html" title="hb-font">
+<link rel="next" href="harfbuzz-hb-set.html" title="hb-set">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-map.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-map.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-font.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-set.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-map"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-map.top_of_page"></a>hb-map</span></h2>
+<p>hb-map — Object representing integer to integer mapping</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-allocation-successful" title="hb_map_allocation_successful ()">hb_map_allocation_successful</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-clear" title="hb_map_clear ()">hb_map_clear</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-create" title="hb_map_create ()">hb_map_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-del" title="hb_map_del ()">hb_map_del</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-destroy" title="hb_map_destroy ()">hb_map_destroy</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get" title="hb_map_get ()">hb_map_get</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-empty" title="hb_map_get_empty ()">hb_map_get_empty</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-population" title="hb_map_get_population ()">hb_map_get_population</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-get-user-data" title="hb_map_get_user_data ()">hb_map_get_user_data</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-has" title="hb_map_has ()">hb_map_has</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-is-empty" title="hb_map_is_empty ()">hb_map_is_empty</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-reference" title="hb_map_reference ()">hb_map_reference</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set" title="hb_map_set ()">hb_map_set</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-map.html#hb-map-set-user-data" title="hb_map_set_user_data ()">hb_map_set_user_data</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<a name="hb-map-t"></a><div class="refsect1">
+<a name="harfbuzz-hb-map.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-map.html#HB-MAP-VALUE-INVALID:CAPS" title="HB_MAP_VALUE_INVALID">HB_MAP_VALUE_INVALID</a></td>
+</tr>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-map.html#hb-map-t">hb_map_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+    <span class="lineart">╰──</span> hb_map_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.description"></a><h2>Description</h2>
+<p>Map objects are integer-to-integer hash-maps.  Currently they are
+not used in the HarfBuzz public API, but are provided for client's
+use if desired.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-map-allocation-successful"></a><h3>hb_map_allocation_successful ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_map_allocation_successful (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-allocation-successful.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-clear"></a><h3>hb_map_clear ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_map_clear (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-clear.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-create"></a><h3>hb_map_create ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+hb_map_create (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p><span class="annotation">[Xconstructor]</span></p>
+<div class="refsect3">
+<a name="hb-map-create.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-del"></a><h3>hb_map_del ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_map_del (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> key</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-del.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-destroy"></a><h3>hb_map_destroy ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_map_destroy (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-map-destroy.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-get"></a><h3>hb_map_get ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="returnvalue">hb_codepoint_t</span></a>
+hb_map_get (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> key</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-get.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-get-empty"></a><h3>hb_map_get_empty ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+hb_map_get_empty (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-get-empty.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-get-population"></a><h3>hb_map_get_population ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_map_get_population (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-get-population.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-get-user-data"></a><h3>hb_map_get_user_data ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span> *
+hb_map_get_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-map-get-user-data.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-map-get-user-data.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-has"></a><h3>hb_map_has ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_map_has (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> key</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-has.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-is-empty"></a><h3>hb_map_is_empty ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_map_is_empty (<em class="parameter"><code>const <a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-is-empty.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-reference"></a><h3>hb_map_reference ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="returnvalue">hb_map_t</span></a> *
+hb_map_reference (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-map-reference.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-map-reference.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-set"></a><h3>hb_map_set ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_map_set (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> key</code></em>,
+            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> value</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-map-set.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-set-user-data"></a><h3>hb_map_set_user_data ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_map_set_user_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-map.html#hb-map-t"><span class="type">hb_map_t</span></a> *map</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t"><span class="type">hb_user_data_key_t</span></a> *key</code></em>,
+                      <em class="parameter"><code><span class="type">void</span> *data</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="type">hb_bool_t</span></a> replace</code></em>);</pre>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="hb-map-set-user-data.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>map</p></td>
+<td class="parameter_description"><p>a map.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-7-7.html#api-index-1.7.7">1.7.7</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-map.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="HB-MAP-VALUE-INVALID:CAPS"></a><h3>HB_MAP_VALUE_INVALID</h3>
+<pre class="programlisting">#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1)
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-map-t"></a><h3>hb_map_t</h3>
+<pre class="programlisting">typedef struct hb_map_t hb_map_t;
+</pre>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-ot-color.html b/docs/html/harfbuzz-hb-ot-color.html
new file mode 100644 (file)
index 0000000..c7bc734
--- /dev/null
@@ -0,0 +1,723 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-ot-color: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="ch10.html" title="OpenType API">
+<link rel="next" href="harfbuzz-hb-ot-font.html" title="hb-ot-font">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-ot-color.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-ot-color.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch10.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-font.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-ot-color"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-color.top_of_page"></a>hb-ot-color</span></h2>
+<p>hb-ot-color — OpenType Color Fonts</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#HB-COLOR:CAPS" title="HB_COLOR()">HB_COLOR</a><span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-alpha" title="hb_color_get_alpha()">hb_color_get_alpha</a><span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-blue" title="hb_color_get_blue()">hb_color_get_blue</a><span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-green" title="hb_color_get_green()">hb_color_get_green</a><span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-color-get-red" title="hb_color_get_red()">hb_color_get_red</a><span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-get-layers" title="hb_ot_color_glyph_get_layers ()">hb_ot_color_glyph_get_layers</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="returnvalue">hb_blob_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-png" title="hb_ot_color_glyph_reference_png ()">hb_ot_color_glyph_reference_png</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="returnvalue">hb_blob_t</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-svg" title="hb_ot_color_glyph_reference_svg ()">hb_ot_color_glyph_reference_svg</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-layers" title="hb_ot_color_has_layers ()">hb_ot_color_has_layers</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-palettes" title="hb_ot_color_has_palettes ()">hb_ot_color_has_palettes</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-png" title="hb_ot_color_has_png ()">hb_ot_color_has_png</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-has-svg" title="hb_ot_color_has_svg ()">hb_ot_color_has_svg</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-color-get-name-id" title="hb_ot_color_palette_color_get_name_id ()">hb_ot_color_palette_color_get_name_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-colors" title="hb_ot_color_palette_get_colors ()">hb_ot_color_palette_get_colors</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-count" title="hb_ot_color_palette_get_count ()">hb_ot_color_palette_get_count</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" title="enum hb_ot_color_palette_flags_t"><span class="returnvalue">hb_ot_color_palette_flags_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-flags" title="hb_ot_color_palette_get_flags ()">hb_ot_color_palette_get_flags</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-name-id" title="hb_ot_color_palette_get_name_id ()">hb_ot_color_palette_get_name_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-color.html#hb-color-t" title="hb_color_t">hb_color_t</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" title="enum hb_ot_color_palette_flags_t">hb_ot_color_palette_flags_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
+    <span class="lineart">╰──</span> hb_ot_color_palette_flags_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.description"></a><h2>Description</h2>
+<p>Functions for fetching color-font information from OpenType font faces.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="HB-COLOR:CAPS"></a><h3>HB_COLOR()</h3>
+<pre class="programlisting">#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-color-get-alpha"></a><h3>hb_color_get_alpha()</h3>
+<pre class="programlisting">#define hb_color_get_alpha(color) ((color) &amp; 0xFF)
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-color-get-blue"></a><h3>hb_color_get_blue()</h3>
+<pre class="programlisting">#define hb_color_get_blue(color) (((color) &gt;&gt; 24) &amp; 0xFF)
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-color-get-green"></a><h3>hb_color_get_green()</h3>
+<pre class="programlisting">#define hb_color_get_green(color) (((color) &gt;&gt; 16) &amp; 0xFF)
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-color-get-red"></a><h3>hb_color_get_red()</h3>
+<pre class="programlisting">#define hb_color_get_red(color)            (((color) &gt;&gt; 8) &amp; 0xFF)
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-glyph-get-layers"></a><h3>hb_ot_color_glyph_get_layers ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_color_glyph_get_layers (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> glyph</code></em>,
+                              <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                              <em class="parameter"><code>unsigned <span class="type">int</span> *count</code></em>,
+                              <em class="parameter"><code><span class="type">hb_ot_color_layer_t</span> *layers</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-get-layers.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>glyph</p></td>
+<td class="parameter_description"><p>a layered color glyph id.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start_offset</p></td>
+<td class="parameter_description"><p>starting offset of layers.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>count</p></td>
+<td class="parameter_description"><p> gets number of layers available to be written on buffer
+and returns number of written layers. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL may be passed instead of a pointer to a location."><span class="acronym">optional</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>layers</p></td>
+<td class="parameter_description"><p> layers buffer to buffer. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=count][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL may be passed instead of a pointer to a location."><span class="acronym">optional</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-get-layers.returns"></a><h4>Returns</h4>
+<p> Total number of layers a layered color glyph have.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-glyph-reference-png"></a><h3>hb_ot_color_glyph_reference_png ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="returnvalue">hb_blob_t</span></a> *
+hb_ot_color_glyph_reference_png (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> glyph</code></em>);</pre>
+<p>Get PNG image for a glyph.</p>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-reference-png.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>a font object, not face. upem should be set on
+that font object if one wants to get optimal png blob, otherwise
+return the biggest one</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>glyph</p></td>
+<td class="parameter_description"><p>a glyph index.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-reference-png.returns"></a><h4>Returns</h4>
+<p> respective PNG blob of the glyph, if available. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-glyph-reference-svg"></a><h3>hb_ot_color_glyph_reference_svg ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-blob.html#hb-blob-t"><span class="returnvalue">hb_blob_t</span></a> *
+hb_ot_color_glyph_reference_svg (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> glyph</code></em>);</pre>
+<p>Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.</p>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-reference-svg.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>glyph</p></td>
+<td class="parameter_description"><p>a svg glyph index.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-glyph-reference-svg.returns"></a><h4>Returns</h4>
+<p> respective svg blob of the glyph, if available. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-has-layers"></a><h3>hb_ot_color_has_layers ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_color_has_layers (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-has-layers.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-has-layers.returns"></a><h4>Returns</h4>
+<p> whether COLR table is available.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-has-palettes"></a><h3>hb_ot_color_has_palettes ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_color_has_palettes (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-has-palettes.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-has-palettes.returns"></a><h4>Returns</h4>
+<p> whether CPAL table is available.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-has-png"></a><h3>hb_ot_color_has_png ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_color_has_png (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<p>Check whether <em class="parameter"><code>face</code></em>
+ has PNG glyph images (either CBDT or sbix tables).</p>
+<p>Returns true if available, false otherwise.</p>
+<div class="refsect3">
+<a name="hb-ot-color-has-png.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-has-svg"></a><h3>hb_ot_color_has_svg ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_color_has_svg (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<p>Check whether <em class="parameter"><code>face</code></em>
+ has SVG glyph images.</p>
+<p>Returns true if available, false otherwise.</p>
+<div class="refsect3">
+<a name="hb-ot-color-has-svg.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-color-get-name-id"></a><h3>hb_ot_color_palette_color_get_name_id ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+hb_ot_color_palette_color_get_name_id (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                       <em class="parameter"><code>unsigned <span class="type">int</span> color_index</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-palette-color-get-name-id.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>color_index</p></td>
+<td class="parameter_description"><p>palette entry index.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-palette-color-get-name-id.returns"></a><h4>Returns</h4>
+<p> Name ID associated with a palette entry, e.g. eye color</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-get-colors"></a><h3>hb_ot_color_palette_get_colors ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_color_palette_get_colors (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> palette_index</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> *color_count</code></em>,
+                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-color.html#hb-color-t" title="hb_color_t"><span class="type">hb_color_t</span></a> *colors</code></em>);</pre>
+<p>Retrieves the colors in a color palette.</p>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-colors.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>palette_index</p></td>
+<td class="parameter_description"><p>the index of the color palette whose colors
+are being requested.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start_offset</p></td>
+<td class="parameter_description"><p>the index of the first color being requested.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>color_count</p></td>
+<td class="parameter_description"><p> on input, how many colors
+can be maximally stored into the <em class="parameter"><code>colors</code></em>
+array;
+on output, how many colors were actually stored. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL may be passed instead of a pointer to a location."><span class="acronym">optional</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>colors</p></td>
+<td class="parameter_description"><p>               an array of <a class="link" href="harfbuzz-hb-ot-color.html#hb-color-t" title="hb_color_t"><span class="type">hb_color_t</span></a> records. After calling
+this function, <em class="parameter"><code>colors</code></em>
+will be filled with
+the palette colors. If <em class="parameter"><code>colors</code></em>
+is NULL, the function
+will just return the number of total colors
+without storing any actual colors; this can be used
+for allocating a buffer of suitable size before calling
+<a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-colors" title="hb_ot_color_palette_get_colors ()"><code class="function">hb_ot_color_palette_get_colors()</code></a> a second time. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=color_count][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL may be passed instead of a pointer to a location."><span class="acronym">optional</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-colors.returns"></a><h4>Returns</h4>
+<p> the total number of colors in the palette.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-get-count"></a><h3>hb_ot_color_palette_get_count ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_color_palette_get_count (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-count.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-count.returns"></a><h4>Returns</h4>
+<p> the number of color palettes in <em class="parameter"><code>face</code></em>
+, or zero if <em class="parameter"><code>face</code></em>
+has
+no colors.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-get-flags"></a><h3>hb_ot_color_palette_get_flags ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" title="enum hb_ot_color_palette_flags_t"><span class="returnvalue">hb_ot_color_palette_flags_t</span></a>
+hb_ot_color_palette_get_flags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                               <em class="parameter"><code>unsigned <span class="type">int</span> palette_index</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-flags.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>palette_index</p></td>
+<td class="parameter_description"><p>the index of the color palette whose flags are being requested</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-flags.returns"></a><h4>Returns</h4>
+<p> the flags for the requested color palette.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-get-name-id"></a><h3>hb_ot_color_palette_get_name_id ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+hb_ot_color_palette_get_name_id (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                 <em class="parameter"><code>unsigned <span class="type">int</span> palette_index</code></em>);</pre>
+<p>Retrieves the name id of a color palette. For example, a color font can
+have themed palettes like "Spring", "Summer", "Fall", and "Winter".</p>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-name-id.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>a font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>palette_index</p></td>
+<td class="parameter_description"><p>the index of the color palette whose name is being requested.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-color-palette-get-name-id.returns"></a><h4>Returns</h4>
+<p> an identifier within <em class="parameter"><code>face</code></em>
+'s <code class="literal">name</code> table.
+If the requested palette has no name the result is <span class="type">HB_OT_NAME_ID_INVALID</span>.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-color.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="hb-color-t"></a><h3>hb_color_t</h3>
+<pre class="programlisting">typedef uint32_t hb_color_t;
+</pre>
+<p>Data type for holding color values.</p>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-color-palette-flags-t"></a><h3>enum hb_ot_color_palette_flags_t</h3>
+<div class="refsect3">
+<a name="hb-ot-color-palette-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-OT-COLOR-PALETTE-FLAG-DEFAULT:CAPS"></a>HB_OT_COLOR_PALETTE_FLAG_DEFAULT</p></td>
+<td class="enum_member_description">
+<p>default indicating that there is nothing special
+  to note about a color palette.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-OT-COLOR-PALETTE-FLAG-USABLE-WITH-LIGHT-BACKGROUND:CAPS"></a>HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND</p></td>
+<td class="enum_member_description">
+<p>flag indicating that the color
+  palette is appropriate to use when displaying the font on a light background such as white.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-OT-COLOR-PALETTE-FLAG-USABLE-WITH-DARK-BACKGROUND:CAPS"></a>HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND</p></td>
+<td class="enum_member_description">
+<p>flag indicating that the color
+  palette is appropriate to use when displaying the font on a dark background such as black.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index f1254f5..02c7686 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-ot-font: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">
-<link rel="next" href="harfbuzz-hb-ot-shape.html" title="hb-ot-shape">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-color.html" title="hb-ot-color">
+<link rel="next" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-ot-font.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot-tag.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot-shape.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-color.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-layout.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-ot-font"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-font.top_of_page"></a>hb-ot-font</span></h2>
-<p>hb-ot-font</p>
+<p>hb-ot-font — OpenType font implementation</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-ot-font.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-ot-font.description"></a><h2>Description</h2>
+<p>Functions for using OpenType fonts with <a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a>.  Not that fonts returned
+by <a class="link" href="harfbuzz-hb-font.html#hb-font-create" title="hb_font_create ()"><code class="function">hb_font_create()</code></a> default to using these functions, so most clients would
+never need to call these functions directly.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-font.functions_details"></a><h2>Functions</h2>
@@ -65,6 +73,6 @@ hb_ot_font_set_funcs (<em class="parameter"><code><a class="link" href="harfbuzz
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 4bab397..ce6c420 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-ot-layout: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot.html" title="hb-ot">
-<link rel="next" href="harfbuzz-hb-ot-tag.html" title="hb-ot-tag">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-font.html" title="hb-ot-font">
+<link rel="next" href="harfbuzz-hb-ot-math.html" title="hb-ot-math">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-ot-layout.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot-tag.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-font.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-math.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-ot-layout"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-layout.top_of_page"></a>hb-ot-layout</span></h2>
-<p>hb-ot-layout</p>
+<p>hb-ot-layout — OpenType Layout</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 <tbody>
 <tr>
 <td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-script" title="hb_ot_tag_to_script ()">hb_ot_tag_to_script</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-from-script-and-language" title="hb_ot_tags_from_script_and_language ()">hb_ot_tags_from_script_and_language</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-tags-to-script-and-language" title="hb_ot_tags_to_script_and_language ()">hb_ot_tags_to_script_and_language</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
 </td>
 </tr>
 <tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-features" title="hb_ot_layout_collect_features ()">hb_ot_layout_collect_features</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-characters" title="hb_ot_layout_feature_get_characters ()">hb_ot_layout_feature_get_characters</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
 <td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
 </td>
 </tr>
 <tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-name-ids" title="hb_ot_layout_feature_get_name_ids ()">hb_ot_layout_feature_get_name_ids</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
 <td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
 </td>
 </tr>
 <tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-find-language" title="hb_ot_layout_script_find_language ()">hb_ot_layout_script_find_language</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
 <td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-choose-script" title="hb_ot_layout_table_choose_script ()">hb_ot_layout_table_choose_script</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-select-language" title="hb_ot_layout_script_select_language ()">hb_ot_layout_script_select_language</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 </td>
 </tr>
 <tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-find-script" title="hb_ot_layout_table_find_script ()">hb_ot_layout_table_find_script</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-feature-tags" title="hb_ot_layout_table_get_feature_tags ()">hb_ot_layout_table_get_feature_tags</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-feature-tags" title="hb_ot_layout_table_get_feature_tags ()">hb_ot_layout_table_get_feature_tags</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-script-tags" title="hb_ot_layout_table_get_script_tags ()">hb_ot_layout_table_get_script_tags</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <td class="function_type">unsigned <span class="returnvalue">int</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-script-tags" title="hb_ot_layout_table_get_script_tags ()">hb_ot_layout_table_get_script_tags</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-lookup-count" title="hb_ot_layout_table_get_lookup_count ()">hb_ot_layout_table_get_lookup_count</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-lookup-count" title="hb_ot_layout_table_get_lookup_count ()">hb_ot_layout_table_get_lookup_count</a> <span class="c_punctuation">()</span>
+<a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-select-script" title="hb_ot_layout_table_select_script ()">hb_ot_layout_table_select_script</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tr>
 <tbody>
 <tr>
 <td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-LANGUAGE:CAPS" title="HB_OT_MAX_TAGS_PER_LANGUAGE">HB_OT_MAX_TAGS_PER_LANGUAGE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-SCRIPT:CAPS" title="HB_OT_MAX_TAGS_PER_SCRIPT">HB_OT_MAX_TAGS_PER_SCRIPT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS" title="HB_OT_TAG_DEFAULT_LANGUAGE">HB_OT_TAG_DEFAULT_LANGUAGE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS" title="HB_OT_TAG_DEFAULT_SCRIPT">HB_OT_TAG_DEFAULT_SCRIPT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-DEFAULT-LANGUAGE-INDEX:CAPS" title="HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX">HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX</a></td>
 </tr>
 <tr>
 </tr>
 <tr>
 <td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-BASE:CAPS" title="HB_OT_TAG_BASE">HB_OT_TAG_BASE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="harfbuzz-hb-ot-layout.html#HB-OT-TAG-GDEF:CAPS" title="HB_OT_TAG_GDEF">HB_OT_TAG_GDEF</a></td>
 </tr>
 <tr>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-layout.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">╰──</span> hb_ot_layout_glyph_class_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-ot-layout.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-ot-layout.description"></a><h2>Description</h2>
+<p>Functions for querying OpenType Layout features in the font face.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-layout.functions_details"></a><h2>Functions</h2>
 <div class="refsect2">
+<a name="hb-ot-tag-to-language"></a><h3>hb_ot_tag_to_language ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
+hb_ot_tag_to_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>);</pre>
+<div class="refsect3">
+<a name="hb-ot-tag-to-language.returns"></a><h4>Returns</h4>
+<p>. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-tag-to-script"></a><h3>hb_ot_tag_to_script ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
+hb_ot_tag_to_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-tags-from-script-and-language"></a><h3>hb_ot_tags_from_script_and_language ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_ot_tags_from_script_and_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> script</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> *script_count</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *script_tags</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> *language_count</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *language_tags</code></em>);</pre>
+<p>Converts an <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> and an <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> to script and language tags.</p>
+<div class="refsect3">
+<a name="hb-ot-tags-from-script-and-language.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>script</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> to convert.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> to convert.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>script_count</p></td>
+<td class="parameter_description"><p> maximum number of script tags to retrieve (IN)
+and actual number of script tags retrieved (OUT). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>script_tags</p></td>
+<td class="parameter_description"><p> array of size at least <em class="parameter"><code>script_count</code></em>
+to store the
+script tag results. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language_count</p></td>
+<td class="parameter_description"><p> maximum number of language tags to retrieve
+(IN) and actual number of language tags retrieved (OUT). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language_tags</p></td>
+<td class="parameter_description"><p> array of size at least <em class="parameter"><code>language_count</code></em>
+to store
+the language tag results. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-tags-to-script-and-language"></a><h3>hb_ot_tags_to_script_and_language ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_ot_tags_to_script_and_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> script_tag</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> language_tag</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> *script</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> *language</code></em>);</pre>
+<p>Converts a script tag and a language tag to an <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> and an
+<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a>.</p>
+<div class="refsect3">
+<a name="hb-ot-tags-to-script-and-language.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>script_tag</p></td>
+<td class="parameter_description"><p>a script tag</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language_tag</p></td>
+<td class="parameter_description"><p>a language tag</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>script</p></td>
+<td class="parameter_description"><p> the <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> corresponding to <em class="parameter"><code>script_tag</code></em>
+(OUT). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p> the <a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> corresponding to <em class="parameter"><code>script_tag</code></em>
+and
+<em class="parameter"><code>language_tag</code></em>
+(OUT). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-ot-layout-collect-lookups"></a><h3>hb_ot_layout_collect_lookups ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_ot_layout_collect_lookups (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
@@ -344,6 +544,84 @@ hb_ot_layout_collect_lookups (<em class="parameter"><code><a class="link" href="
 </div>
 <hr>
 <div class="refsect2">
+<a name="hb-ot-layout-collect-features"></a><h3>hb_ot_layout_collect_features ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_ot_layout_collect_features (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                               <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                               <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *scripts</code></em>,
+                               <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *languages</code></em>,
+                               <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *features</code></em>,
+                               <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *feature_indexes</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-1-8-5.html#api-index-1.8.5">1.8.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-layout-feature-get-characters"></a><h3>hb_ot_layout_feature_get_characters ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_layout_feature_get_characters (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> feature_index</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> *char_count</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *characters</code></em>);</pre>
+<p>Fetches characters listed by designer under feature parameters for "Character
+Variant" ("cvXX") features.</p>
+<div class="refsect3">
+<a name="hb-ot-layout-feature-get-characters.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> to work upon</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>table_tag</p></td>
+<td class="parameter_description"><p>table tag to query, "GSUB" or "GPOS".</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>feature_index</p></td>
+<td class="parameter_description"><p>index of feature to query.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>start_offset</p></td>
+<td class="parameter_description"><p>In case the resulting char_count was equal to its input value, there
+is a chance there were more characters on the tag so this API can be
+called with an offset till resulting char_count gets to a number
+lower than input buffer (or consider using just a bigger buffer for
+one shot copying).</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>char_count</p></td>
+<td class="parameter_description"><p> The count of characters for which this feature
+provides glyph variants. (May be zero.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>characters</p></td>
+<td class="parameter_description"><p> A buffer pointer. The Unicode codepoints
+of the characters for which this feature provides glyph variants. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=char_count]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-layout-feature-get-characters.returns"></a><h4>Returns</h4>
+<p> Number of total sample characters in the cvXX feature.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-ot-layout-feature-get-lookups"></a><h3>hb_ot_layout_feature_get_lookups ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
 hb_ot_layout_feature_get_lookups (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
@@ -356,6 +634,84 @@ hb_ot_layout_feature_get_lookups (<em class="parameter"><code><a class="link" hr
 </div>
 <hr>
 <div class="refsect2">
+<a name="hb-ot-layout-feature-get-name-ids"></a><h3>hb_ot_layout_feature_get_name_ids ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_layout_feature_get_name_ids (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                                   <em class="parameter"><code>unsigned <span class="type">int</span> feature_index</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> *label_id</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> *tooltip_id</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> *sample_id</code></em>,
+                                   <em class="parameter"><code>unsigned <span class="type">int</span> *num_named_parameters</code></em>,
+                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> *first_param_id</code></em>);</pre>
+<p>Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
+"Character Variant" ('cvXX') features.</p>
+<div class="refsect3">
+<a name="hb-ot-layout-feature-get-name-ids.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> to work upon</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>table_tag</p></td>
+<td class="parameter_description"><p>table tag to query, "GSUB" or "GPOS".</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>feature_index</p></td>
+<td class="parameter_description"><p>index of feature to query.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>label_id</p></td>
+<td class="parameter_description"><p> The ‘name’ table name ID that specifies a string
+for a user-interface label for this feature. (May be NULL.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>tooltip_id</p></td>
+<td class="parameter_description"><p> The ‘name’ table name ID that specifies a string
+that an application can use for tooltip text for this
+feature. (May be NULL.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sample_id</p></td>
+<td class="parameter_description"><p> The ‘name’ table name ID that specifies sample text
+that illustrates the effect of this feature. (May be NULL.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>num_named_parameters</p></td>
+<td class="parameter_description"><p>  Number of named parameters. (May be zero.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>first_param_id</p></td>
+<td class="parameter_description"><p> The first ‘name’ table name ID used to specify
+strings for user-interface labels for the feature
+parameters. (Must be zero if numParameters is zero.). </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-layout-feature-get-name-ids.returns"></a><h4>Returns</h4>
+<p> true if data found, false otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-ot-layout-feature-with-variations-get-lookups"></a><h3>hb_ot_layout_feature_with_variations_get_lookups ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
 hb_ot_layout_feature_with_variations_get_lookups
@@ -412,7 +768,7 @@ hb_ot_layout_get_ligature_carets (<em class="parameter"><code><a class="link" hr
 hb_ot_layout_get_size_params (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> *design_size</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> *subfamily_id</code></em>,
-                              <em class="parameter"><code>unsigned <span class="type">int</span> *subfamily_name_id</code></em>,
+                              <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> *subfamily_name_id</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> *range_start</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> *range_end</code></em>);</pre>
 <p class="since">Since: <a class="link" href="api-index-0-9-10.html#api-index-0.9.10">0.9.10</a></p>
@@ -528,7 +884,7 @@ hb_ot_layout_lookups_substitute_closure
                                 <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *glyphs</code></em>);</pre>
 <p>Compute the transitive closure of glyphs needed for all of the
 provided lookups.</p>
-<p class="since">Since: 1.8.1</p>
+<p class="since">Since: <a class="link" href="api-index-1-8-1.html#api-index-1.8.1">1.8.1</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -543,16 +899,6 @@ hb_ot_layout_lookup_would_substitute (<em class="parameter"><code><a class="link
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-ot-layout-script-find-language"></a><h3>hb_ot_layout_script_find_language ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_ot_layout_script_find_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
-                                   <em class="parameter"><code>unsigned <span class="type">int</span> script_index</code></em>,
-                                   <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> language_tag</code></em>,
-                                   <em class="parameter"><code>unsigned <span class="type">int</span> *language_index</code></em>);</pre>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-ot-layout-script-get-language-tags"></a><h3>hb_ot_layout_script_get_language_tags ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
 hb_ot_layout_script_get_language_tags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
@@ -564,13 +910,15 @@ hb_ot_layout_script_get_language_tags (<em class="parameter"><code><a class="lin
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-ot-layout-table-choose-script"></a><h3>hb_ot_layout_table_choose_script ()</h3>
+<a name="hb-ot-layout-script-select-language"></a><h3>hb_ot_layout_script_select_language ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_ot_layout_table_choose_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
-                                  <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *script_tags</code></em>,
-                                  <em class="parameter"><code>unsigned <span class="type">int</span> *script_index</code></em>,
-                                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *chosen_script</code></em>);</pre>
+hb_ot_layout_script_select_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> script_index</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> language_count</code></em>,
+                                     <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *language_tags</code></em>,
+                                     <em class="parameter"><code>unsigned <span class="type">int</span> *language_index</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -585,15 +933,6 @@ hb_ot_layout_table_find_feature_variations
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-ot-layout-table-find-script"></a><h3>hb_ot_layout_table_find_script ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
-hb_ot_layout_table_find_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> script_tag</code></em>,
-                                <em class="parameter"><code>unsigned <span class="type">int</span> *script_index</code></em>);</pre>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-ot-layout-table-get-feature-tags"></a><h3>hb_ot_layout_table_get_feature_tags ()</h3>
 <pre class="programlisting">unsigned <span class="returnvalue">int</span>
 hb_ot_layout_table_get_feature_tags (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
@@ -622,6 +961,18 @@ hb_ot_layout_table_get_lookup_count (<em class="parameter"><code><a class="link"
 </div>
 <hr>
 <div class="refsect2">
+<a name="hb-ot-layout-table-select-script"></a><h3>hb_ot_layout_table_select_script ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_layout_table_select_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> table_tag</code></em>,
+                                  <em class="parameter"><code>unsigned <span class="type">int</span> script_count</code></em>,
+                                  <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *script_tags</code></em>,
+                                  <em class="parameter"><code>unsigned <span class="type">int</span> *script_index</code></em>,
+                                  <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *chosen_script</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="hb-ot-shape-plan-collect-lookups"></a><h3>hb_ot_shape_plan_collect_lookups ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_ot_shape_plan_collect_lookups (<em class="parameter"><code><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="type">hb_shape_plan_t</span></a> *shape_plan</code></em>,
@@ -644,6 +995,32 @@ hb_ot_layout_language_get_required_feature_index
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-layout.other_details"></a><h2>Types and Values</h2>
 <div class="refsect2">
+<a name="HB-OT-MAX-TAGS-PER-LANGUAGE:CAPS"></a><h3>HB_OT_MAX_TAGS_PER_LANGUAGE</h3>
+<pre class="programlisting">#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-MAX-TAGS-PER-SCRIPT:CAPS"></a><h3>HB_OT_MAX_TAGS_PER_SCRIPT</h3>
+<pre class="programlisting">#define HB_OT_MAX_TAGS_PER_SCRIPT 3u
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-DEFAULT-LANGUAGE:CAPS"></a><h3>HB_OT_TAG_DEFAULT_LANGUAGE</h3>
+<pre class="programlisting">#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-DEFAULT-SCRIPT:CAPS"></a><h3>HB_OT_TAG_DEFAULT_SCRIPT</h3>
+<pre class="programlisting">#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="HB-OT-LAYOUT-DEFAULT-LANGUAGE-INDEX:CAPS"></a><h3>HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX</h3>
 <pre class="programlisting">#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu
 </pre>
@@ -668,6 +1045,12 @@ hb_ot_layout_language_get_required_feature_index
 </div>
 <hr>
 <div class="refsect2">
+<a name="HB-OT-TAG-BASE:CAPS"></a><h3>HB_OT_TAG_BASE</h3>
+<pre class="programlisting">#define HB_OT_TAG_BASE HB_TAG('B','A','S','E')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="HB-OT-TAG-GDEF:CAPS"></a><h3>HB_OT_TAG_GDEF</h3>
 <pre class="programlisting">#define HB_OT_TAG_GDEF HB_TAG('G','D','E','F')
 </pre>
@@ -734,6 +1117,6 @@ hb_ot_layout_language_get_required_feature_index
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 0c85bdd..b803cef 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-ot-math: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot-shape.html" title="hb-ot-shape">
-<link rel="next" href="harfbuzz-hb-shape-plan.html" title="hb-shape-plan">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">
+<link rel="next" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-ot-math.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot-shape.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-shape-plan.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-layout.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-name.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-ot-math"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-math.top_of_page"></a>hb-ot-math</span></h2>
-<p>hb-ot-math</p>
+<p>hb-ot-math — OpenType Math information</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-math.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">├──</span> hb_ot_math_glyph_part_t
     <span class="lineart">╰──</span> hb_ot_math_glyph_variant_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">├──</span> hb_ot_math_constant_t
     <span class="lineart">╰──</span> hb_ot_math_kern_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
     <span class="lineart">╰──</span> hb_ot_math_glyph_part_flags_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-ot-math.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-ot-math.description"></a><h2>Description</h2>
+<p>Functions for fetching mathematics layout data from OpenType fonts.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-math.functions_details"></a><h2>Functions</h2>
@@ -956,6 +962,6 @@ to store the result</p></td>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-ot-name.html b/docs/html/harfbuzz-hb-ot-name.html
new file mode 100644 (file)
index 0000000..68e3a97
--- /dev/null
@@ -0,0 +1,327 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-ot-name: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-math.html" title="hb-ot-math">
+<link rel="next" href="harfbuzz-hb-ot-shape.html" title="hb-ot-shape">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-ot-name.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-math.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-shape.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-ot-name"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-name.top_of_page"></a>hb-ot-name</span></h2>
+<p>hb-ot-name — OpenType font name information</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">const <span class="returnvalue">hb_ot_name_entry_t</span> *
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-list-names" title="hb_ot_name_list_names ()">hb_ot_name_list_names</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf16" title="hb_ot_name_get_utf16 ()">hb_ot_name_get_utf16</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf32" title="hb_ot_name_get_utf32 ()">hb_ot_name_get_utf32</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf8" title="hb_ot_name_get_utf8 ()">hb_ot_name_get_utf8</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody><tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t">hb_ot_name_id_t</a></td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.description"></a><h2>Description</h2>
+<p>Functions for fetching name strings from OpenType fonts.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-ot-name-list-names"></a><h3>hb_ot_name_list_names ()</h3>
+<pre class="programlisting">const <span class="returnvalue">hb_ot_name_entry_t</span> *
+hb_ot_name_list_names (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                       <em class="parameter"><code>unsigned <span class="type">int</span> *num_entries</code></em>);</pre>
+<p>Enumerates all available name IDs and language combinations. Returned
+array is owned by the <em class="parameter"><code>face</code></em>
+ and should not be modified.  It can be
+used as long as <em class="parameter"><code>face</code></em>
+ is alive.</p>
+<div class="refsect3">
+<a name="hb-ot-name-list-names.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>num_entries</p></td>
+<td class="parameter_description"><p> number of returned entries. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-name-list-names.returns"></a><h4>Returns</h4>
+<p> Array of available name entries. </p>
+<p><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>][<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=num_entries]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-name-get-utf16"></a><h3>hb_ot_name_get_utf16 ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_name_get_utf16 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> name_id</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>,
+                      <em class="parameter"><code>unsigned <span class="type">int</span> *text_size</code></em>,
+                      <em class="parameter"><code><span class="type">uint16_t</span> *text</code></em>);</pre>
+<p>Fetches a font name from the OpenType 'name' table.
+If <em class="parameter"><code>language</code></em>
+ is <a class="link" href="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS" title="HB_LANGUAGE_INVALID"><span class="type">HB_LANGUAGE_INVALID</span></a>, English ("en") is assumed.
+Returns string in UTF-16 encoding.</p>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf16.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>name_id</p></td>
+<td class="parameter_description"><p>OpenType name identifier to fetch.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p>language to fetch the name for.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_size</p></td>
+<td class="parameter_description"><p> input size of <em class="parameter"><code>text</code></em>
+buffer, and output size of
+text written to buffer. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> buffer to write fetched name into. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_size]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf16.returns"></a><h4>Returns</h4>
+<p> full length of the requested string, or 0 if not found.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-name-get-utf32"></a><h3>hb_ot_name_get_utf32 ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_name_get_utf32 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> name_id</code></em>,
+                      <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>,
+                      <em class="parameter"><code>unsigned <span class="type">int</span> *text_size</code></em>,
+                      <em class="parameter"><code><span class="type">uint32_t</span> *text</code></em>);</pre>
+<p>Fetches a font name from the OpenType 'name' table.
+If <em class="parameter"><code>language</code></em>
+ is <a class="link" href="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS" title="HB_LANGUAGE_INVALID"><span class="type">HB_LANGUAGE_INVALID</span></a>, English ("en") is assumed.
+Returns string in UTF-32 encoding.</p>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf32.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>name_id</p></td>
+<td class="parameter_description"><p>OpenType name identifier to fetch.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p>language to fetch the name for.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_size</p></td>
+<td class="parameter_description"><p> input size of <em class="parameter"><code>text</code></em>
+buffer, and output size of
+text written to buffer. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> buffer to write fetched name into. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_size]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf32.returns"></a><h4>Returns</h4>
+<p> full length of the requested string, or 0 if not found.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-name-get-utf8"></a><h3>hb_ot_name_get_utf8 ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_name_get_utf8 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="type">hb_ot_name_id_t</span></a> name_id</code></em>,
+                     <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>,
+                     <em class="parameter"><code>unsigned <span class="type">int</span> *text_size</code></em>,
+                     <em class="parameter"><code><span class="type">char</span> *text</code></em>);</pre>
+<p>Fetches a font name from the OpenType 'name' table.
+If <em class="parameter"><code>language</code></em>
+ is <a class="link" href="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS" title="HB_LANGUAGE_INVALID"><span class="type">HB_LANGUAGE_INVALID</span></a>, English ("en") is assumed.
+Returns string in UTF-8 encoding.</p>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf8.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p>font face.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>name_id</p></td>
+<td class="parameter_description"><p>OpenType name identifier to fetch.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>language</p></td>
+<td class="parameter_description"><p>language to fetch the name for.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text_size</p></td>
+<td class="parameter_description"><p> input size of <em class="parameter"><code>text</code></em>
+buffer, and output size of
+text written to buffer. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>text</p></td>
+<td class="parameter_description"><p> buffer to write fetched name into. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=text_size]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-name-get-utf8.returns"></a><h4>Returns</h4>
+<p> full length of the requested string, or 0 if not found.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-2-1-0.html#api-index-2.1.0">2.1.0</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-name.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="hb-ot-name-id-t"></a><h3>hb_ot_name_id_t</h3>
+<pre class="programlisting">typedef unsigned int hb_ot_name_id_t;
+</pre>
+<p>An integral type representing an OpenType 'name' table name identifier.
+There are predefined name IDs, as well as name IDs return from other
+API.  These can be used to fetch name strings from a font face.</p>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index f33f2a4..30ed441 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-ot-shape: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot-font.html" title="hb-ot-font">
-<link rel="next" href="harfbuzz-hb-ot-math.html" title="hb-ot-math">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-name.html" title="hb-ot-name">
+<link rel="next" href="harfbuzz-hb-ot-var.html" title="hb-ot-var">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-ot-shape.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot-font.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot-math.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-name.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-ot-var.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-ot-shape"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-shape.top_of_page"></a>hb-ot-shape</span></h2>
-<p>hb-ot-shape</p>
+<p>hb-ot-shape — OpenType shaping support</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-ot-shape.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-ot-shape.description"></a><h2>Description</h2>
+<p>Support functions for OpenType shaping related queries.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-ot-shape.functions_details"></a><h2>Functions</h2>
@@ -57,8 +63,8 @@
 <a name="hb-ot-shape-glyphs-closure"></a><h3>hb_ot_shape_glyphs_closure ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_ot_shape_glyphs_closure (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                            <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
+                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                            <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
                             <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>,
                             <em class="parameter"><code><a class="link" href="harfbuzz-hb-set.html#hb-set-t"><span class="type">hb_set_t</span></a> *glyphs</code></em>);</pre>
 <p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
@@ -69,6 +75,6 @@ hb_ot_shape_glyphs_closure (<em class="parameter"><code><a class="link" href="ha
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-ot-tag.html b/docs/html/harfbuzz-hb-ot-tag.html
deleted file mode 100644 (file)
index 2ebf67d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>hb-ot-tag: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">
-<link rel="next" href="harfbuzz-hb-ot-font.html" title="hb-ot-font">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts">
-<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-hb-ot-tag.description" class="shortcut">Description</a></span>
-</td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot-layout.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot-font.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="refentry">
-<a name="harfbuzz-hb-ot-tag"></a><div class="titlepage"></div>
-<div class="refnamediv"><table width="100%"><tr>
-<td valign="top">
-<h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-tag.top_of_page"></a>hb-ot-tag</span></h2>
-<p>hb-ot-tag</p>
-</td>
-<td class="gallery_image" valign="top" align="right"></td>
-</tr></table></div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot-tag.functions"></a><h2>Functions</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="functions_return">
-<col class="functions_name">
-</colgroup>
-<tbody>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="returnvalue">hb_tag_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-from-language" title="hb_ot_tag_from_language ()">hb_ot_tag_from_language</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-language" title="hb_ot_tag_to_language ()">hb_ot_tag_to_language</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-script" title="hb_ot_tag_to_script ()">hb_ot_tag_to_script</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-ot-tag.html#hb-ot-tags-from-script" title="hb_ot_tags_from_script ()">hb_ot_tags_from_script</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot-tag.other"></a><h2>Types and Values</h2>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="name">
-<col class="description">
-</colgroup>
-<tbody>
-<tr>
-<td class="define_keyword">#define</td>
-<td class="function_name"><a class="link" href="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS" title="HB_OT_TAG_DEFAULT_LANGUAGE">HB_OT_TAG_DEFAULT_LANGUAGE</a></td>
-</tr>
-<tr>
-<td class="define_keyword">#define</td>
-<td class="function_name"><a class="link" href="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS" title="HB_OT_TAG_DEFAULT_SCRIPT">HB_OT_TAG_DEFAULT_SCRIPT</a></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot-tag.description"></a><h2>Description</h2>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot-tag.functions_details"></a><h2>Functions</h2>
-<div class="refsect2">
-<a name="hb-ot-tag-from-language"></a><h3>hb_ot_tag_from_language ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="returnvalue">hb_tag_t</span></a>
-hb_ot_tag_from_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="type">hb_language_t</span></a> language</code></em>);</pre>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-ot-tag-to-language"></a><h3>hb_ot_tag_to_language ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-language-t" title="hb_language_t"><span class="returnvalue">hb_language_t</span></a>
-hb_ot_tag_to_language (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-ot-tag-to-language.returns"></a><h4>Returns</h4>
-<p>. </p>
-<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-ot-tag-to-script"></a><h3>hb_ot_tag_to_script ()</h3>
-<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="returnvalue">hb_script_t</span></a>
-hb_ot_tag_to_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> tag</code></em>);</pre>
-</div>
-<hr>
-<div class="refsect2">
-<a name="hb-ot-tags-from-script"></a><h3>hb_ot_tags_from_script ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_ot_tags_from_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t"><span class="type">hb_script_t</span></a> script</code></em>,
-                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *script_tag_1</code></em>,
-                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> *script_tag_2</code></em>);</pre>
-</div>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot-tag.other_details"></a><h2>Types and Values</h2>
-<div class="refsect2">
-<a name="HB-OT-TAG-DEFAULT-LANGUAGE:CAPS"></a><h3>HB_OT_TAG_DEFAULT_LANGUAGE</h3>
-<pre class="programlisting">#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
-</pre>
-</div>
-<hr>
-<div class="refsect2">
-<a name="HB-OT-TAG-DEFAULT-SCRIPT:CAPS"></a><h3>HB_OT_TAG_DEFAULT_SCRIPT</h3>
-<pre class="programlisting">#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
-</pre>
-</div>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-ot-var.html b/docs/html/harfbuzz-hb-ot-var.html
new file mode 100644 (file)
index 0000000..b8e3fd3
--- /dev/null
@@ -0,0 +1,345 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-ot-var: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch10.html" title="OpenType API">
+<link rel="prev" href="harfbuzz-hb-ot-shape.html" title="hb-ot-shape">
+<link rel="next" href="ch11.html" title="Apple Advanced Typography API">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-ot-var.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-ot-var.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch10.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-ot-shape.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch11.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-ot-var"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-ot-var.top_of_page"></a>hb-ot-var</span></h2>
+<p>hb-ot-var — OpenType Font Variations</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-has-data" title="hb_ot_var_has_data ()">hb_ot_var_has_data</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-find-axis-info" title="hb_ot_var_find_axis_info ()">hb_ot_var_find_axis_info</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-count" title="hb_ot_var_get_axis_count ()">hb_ot_var_get_axis_count</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-infos" title="hb_ot_var_get_axis_infos ()">hb_ot_var_get_axis_infos</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-get-named-instance-count" title="hb_ot_var_get_named_instance_count ()">hb_ot_var_get_named_instance_count</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-subfamily-name-id" title="hb_ot_var_named_instance_get_subfamily_name_id ()">hb_ot_var_named_instance_get_subfamily_name_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-postscript-name-id" title="hb_ot_var_named_instance_get_postscript_name_id ()">hb_ot_var_named_instance_get_postscript_name_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">unsigned <span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-design-coords" title="hb_ot_var_named_instance_get_design_coords ()">hb_ot_var_named_instance_get_design_coords</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-variations" title="hb_ot_var_normalize_variations ()">hb_ot_var_normalize_variations</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-coords" title="hb_ot_var_normalize_coords ()">hb_ot_var_normalize_coords</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-ITALIC:CAPS" title="HB_OT_TAG_VAR_AXIS_ITALIC">HB_OT_TAG_VAR_AXIS_ITALIC</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-OPTICAL-SIZE:CAPS" title="HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE">HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-SLANT:CAPS" title="HB_OT_TAG_VAR_AXIS_SLANT">HB_OT_TAG_VAR_AXIS_SLANT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WEIGHT:CAPS" title="HB_OT_TAG_VAR_AXIS_WEIGHT">HB_OT_TAG_VAR_AXIS_WEIGHT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WIDTH:CAPS" title="HB_OT_TAG_VAR_AXIS_WIDTH">HB_OT_TAG_VAR_AXIS_WIDTH</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-ot-var.html#hb-ot-var-axis-flags-t" title="enum hb_ot_var_axis_flags_t">hb_ot_var_axis_flags_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
+    <span class="lineart">╰──</span> hb_ot_var_axis_flags_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-ot.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.description"></a><h2>Description</h2>
+<p>Functions for fetching information about OpenType Variable Fonts.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-ot-var-has-data"></a><h3>hb_ot_var_has_data ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_var_has_data (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<p>This function allows to verify the presence of OpenType variation data on the face.</p>
+<div class="refsect3">
+<a name="hb-ot-var-has-data.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>face</p></td>
+<td class="parameter_description"><p><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> to test</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-ot-var-has-data.returns"></a><h4>Returns</h4>
+<p> true if face has a `fvar' table and false otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-1-4-2.html#api-index-1.4.2">1.4.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-find-axis-info"></a><h3>hb_ot_var_find_axis_info ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_ot_var_find_axis_info (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                          <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-tag-t" title="hb_tag_t"><span class="type">hb_tag_t</span></a> axis_tag</code></em>,
+                          <em class="parameter"><code><span class="type">hb_ot_var_axis_info_t</span> *axis_info</code></em>);</pre>
+<p class="since">Since: 2.2.0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-get-axis-count"></a><h3>hb_ot_var_get_axis_count ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_var_get_axis_count (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-1-4-2.html#api-index-1.4.2">1.4.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-get-axis-infos"></a><h3>hb_ot_var_get_axis_infos ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_var_get_axis_infos (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                          <em class="parameter"><code>unsigned <span class="type">int</span> start_offset</code></em>,
+                          <em class="parameter"><code>unsigned <span class="type">int</span> *axes_count</code></em>,
+                          <em class="parameter"><code><span class="type">hb_ot_var_axis_info_t</span> *axes_array</code></em>);</pre>
+<p class="since">Since: 2.2.0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-get-named-instance-count"></a><h3>hb_ot_var_get_named_instance_count ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_var_get_named_instance_count (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-named-instance-get-subfamily-name-id"></a><h3>hb_ot_var_named_instance_get_subfamily_name_id ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+hb_ot_var_named_instance_get_subfamily_name_id
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> instance_index</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-named-instance-get-postscript-name-id"></a><h3>hb_ot_var_named_instance_get_postscript_name_id ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" title="hb_ot_name_id_t"><span class="returnvalue">hb_ot_name_id_t</span></a>
+hb_ot_var_named_instance_get_postscript_name_id
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> instance_index</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-named-instance-get-design-coords"></a><h3>hb_ot_var_named_instance_get_design_coords ()</h3>
+<pre class="programlisting">unsigned <span class="returnvalue">int</span>
+hb_ot_var_named_instance_get_design_coords
+                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> instance_index</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> *coords_length</code></em>,
+                                <em class="parameter"><code><span class="type">float</span> *coords</code></em>);</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-normalize-variations"></a><h3>hb_ot_var_normalize_variations ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_ot_var_normalize_variations (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                                <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-font.html#hb-variation-t" title="hb_variation_t"><span class="type">hb_variation_t</span></a> *variations</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> variations_length</code></em>,
+                                <em class="parameter"><code><span class="type">int</span> *coords</code></em>,
+                                <em class="parameter"><code>unsigned <span class="type">int</span> coords_length</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-1-4-2.html#api-index-1.4.2">1.4.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-normalize-coords"></a><h3>hb_ot_var_normalize_coords ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_ot_var_normalize_coords (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
+                            <em class="parameter"><code>unsigned <span class="type">int</span> coords_length</code></em>,
+                            <em class="parameter"><code>const <span class="type">float</span> *design_coords</code></em>,
+                            <em class="parameter"><code><span class="type">int</span> *normalized_coords</code></em>);</pre>
+<p class="since">Since: <a class="link" href="api-index-1-4-2.html#api-index-1.4.2">1.4.2</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-ot-var.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="HB-OT-TAG-VAR-AXIS-ITALIC:CAPS"></a><h3>HB_OT_TAG_VAR_AXIS_ITALIC</h3>
+<pre class="programlisting">#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-VAR-AXIS-OPTICAL-SIZE:CAPS"></a><h3>HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE</h3>
+<pre class="programlisting">#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-VAR-AXIS-SLANT:CAPS"></a><h3>HB_OT_TAG_VAR_AXIS_SLANT</h3>
+<pre class="programlisting">#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-VAR-AXIS-WEIGHT:CAPS"></a><h3>HB_OT_TAG_VAR_AXIS_WEIGHT</h3>
+<pre class="programlisting">#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-OT-TAG-VAR-AXIS-WIDTH:CAPS"></a><h3>HB_OT_TAG_VAR_AXIS_WIDTH</h3>
+<pre class="programlisting">#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h')
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-ot-var-axis-flags-t"></a><h3>enum hb_ot_var_axis_flags_t</h3>
+<div class="refsect3">
+<a name="hb-ot-var-axis-flags-t.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="HB-OT-VAR-AXIS-FLAG-HIDDEN:CAPS"></a>HB_OT_VAR_AXIS_FLAG_HIDDEN</p></td>
+<td class="enum_member_description">
+<p>The axis should not be exposed directly in user interfaces.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="HB-OT-VAR-AXIS-FLAG-MAX-VALUE:CAPS"></a>_HB_OT_VAR_AXIS_FLAG_MAX_VALUE</p></td>
+<td> </td>
+<td> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 2.2.0</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-ot.html b/docs/html/harfbuzz-hb-ot.html
deleted file mode 100644 (file)
index 4af82e6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>hb-ot: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-set.html" title="hb-set">
-<link rel="next" href="harfbuzz-hb-ot-layout.html" title="hb-ot-layout">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts">
-<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-hb-ot.description" class="shortcut">Description</a></span>
-</td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-set.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot-layout.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="refentry">
-<a name="harfbuzz-hb-ot"></a><div class="titlepage"></div>
-<div class="refnamediv"><table width="100%"><tr>
-<td valign="top">
-<h2><span class="refentrytitle"><a name="harfbuzz-hb-ot.top_of_page"></a>hb-ot</span></h2>
-<p>hb-ot</p>
-</td>
-<td class="gallery_image" valign="top" align="right"></td>
-</tr></table></div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot.description"></a><h2>Description</h2>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot.functions_details"></a><h2>Functions</h2>
-<p></p>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb-ot.other_details"></a><h2>Types and Values</h2>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
index d05e57d..b07920d 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-set: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">
-<link rel="next" href="harfbuzz-hb-ot.html" title="hb-ot">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-map.html" title="hb-map">
+<link rel="next" href="harfbuzz-hb-shape-plan.html" title="hb-shape-plan">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-set.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-deprecated.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-ot.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-map.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-shape-plan.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-set"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-set.top_of_page"></a>hb-set</span></h2>
-<p>hb-set</p>
+<p>hb-set — Object representing a set of integers</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-set.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_set_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-set.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-set.description"></a><h2>Description</h2>
+<p>Set objects represent a mathematical set of integer values.  They are
+used in non-shaping API to query certain set of characters or glyphs,
+or other integer values.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-set.functions_details"></a><h2>Functions</h2>
@@ -727,7 +735,7 @@ hb_set_is_subset (<em class="parameter"><code>const <a class="link" href="harfbu
 is a subset of (or equal to) <em class="parameter"><code>larger_set</code></em>
 , <code class="literal">FALSE</code> otherwise.</p>
 </div>
-<p class="since">Since: 1.8.1</p>
+<p class="since">Since: <a class="link" href="api-index-1-8-1.html#api-index-1.8.1">1.8.1</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -797,12 +805,12 @@ are greater than current value of <em class="parameter"><code>last</code></em>
 </tr>
 <tr>
 <td class="parameter_name"><p>first</p></td>
-<td class="parameter_description"><p>output first codepoint in the range. </p></td>
+<td class="parameter_description"><p> output first codepoint in the range. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 <tr>
 <td class="parameter_name"><p>last</p></td>
-<td class="parameter_description"><p>input current last and output last codepoint in the range. </p></td>
+<td class="parameter_description"><p> input current last and output last codepoint in the range. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>]</span></td>
 </tr>
 </tbody>
@@ -851,7 +859,7 @@ hb_set_previous (<em class="parameter"><code>const <a class="link" href="harfbuz
 <a name="hb-set-previous.returns"></a><h4>Returns</h4>
 <p> whether there was a previous value.</p>
 </div>
-<p class="since">Since: 1.8.0</p>
+<p class="since">Since: <a class="link" href="api-index-1-8-0.html#api-index-1.8.0">1.8.0</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -882,12 +890,12 @@ are greater than current value of <em class="parameter"><code>last</code></em>
 </tr>
 <tr>
 <td class="parameter_name"><p>first</p></td>
-<td class="parameter_description"><p>input current first and output first codepoint in the range. </p></td>
+<td class="parameter_description"><p> input current first and output first codepoint in the range. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for input and for returning results. Default is transfer full."><span class="acronym">inout</span></acronym>]</span></td>
 </tr>
 <tr>
 <td class="parameter_name"><p>last</p></td>
-<td class="parameter_description"><p>output last codepoint in the range. </p></td>
+<td class="parameter_description"><p> output last codepoint in the range. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 </tbody>
@@ -897,7 +905,7 @@ are greater than current value of <em class="parameter"><code>last</code></em>
 <a name="hb-set-previous-range.returns"></a><h4>Returns</h4>
 <p> whether there was a previous range.</p>
 </div>
-<p class="since">Since: 1.8.0</p>
+<p class="since">Since: <a class="link" href="api-index-1-8-0.html#api-index-1.8.0">1.8.0</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -1063,6 +1071,6 @@ hb_set_union (<em class="parameter"><code><a class="link" href="harfbuzz-hb-set.
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 13f235f..3986cab 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-shape-plan: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-ot-math.html" title="hb-ot-math">
-<link rel="next" href="harfbuzz-hb-glib.html" title="hb-glib">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-set.html" title="hb-set">
+<link rel="next" href="harfbuzz-hb-shape.html" title="hb-shape">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-shape-plan.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-ot-math.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-glib.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-set.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-shape.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-shape-plan"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-shape-plan.top_of_page"></a>hb-shape-plan</span></h2>
-<p>hb-shape-plan</p>
+<p>hb-shape-plan — Object representing a shaping plan</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-shape-plan.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_shape_plan_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-shape-plan.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-shape-plan.description"></a><h2>Description</h2>
+<p>Shape plans are not used for shaping directly, but can be access to query
+certain information about how shaping will perform given a set of input
+parameters (script, language, direction, features, etc.)
+Most client would not need to deal with shape plans directly.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-shape-plan.functions_details"></a><h2>Functions</h2>
 <a name="hb-shape-plan-create"></a><h3>hb_shape_plan_create ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="returnvalue">hb_shape_plan_t</span></a> *
 hb_shape_plan_create (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                      <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
-                      <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
+                      <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
+                      <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
                       <em class="parameter"><code>unsigned <span class="type">int</span> num_user_features</code></em>,
                       <em class="parameter"><code>const <span class="type">char</span> * const *shaper_list</code></em>);</pre>
 <p><span class="annotation">[Xconstructor]</span></p>
@@ -197,8 +206,8 @@ hb_shape_plan_create (<em class="parameter"><code><a class="link" href="harfbuzz
 <a name="hb-shape-plan-create-cached"></a><h3>hb_shape_plan_create_cached ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="returnvalue">hb_shape_plan_t</span></a> *
 hb_shape_plan_create_cached (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                             <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
-                             <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
+                             <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
+                             <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
                              <em class="parameter"><code>unsigned <span class="type">int</span> num_user_features</code></em>,
                              <em class="parameter"><code>const <span class="type">char</span> * const *shaper_list</code></em>);</pre>
 <div class="refsect3">
@@ -235,8 +244,8 @@ hb_shape_plan_create_cached (<em class="parameter"><code><a class="link" href="h
 <a name="hb-shape-plan-create2"></a><h3>hb_shape_plan_create2 ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="returnvalue">hb_shape_plan_t</span></a> *
 hb_shape_plan_create2 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                       <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
-                       <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
+                       <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
+                       <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
                        <em class="parameter"><code>unsigned <span class="type">int</span> num_user_features</code></em>,
                        <em class="parameter"><code>const <span class="type">int</span> *coords</code></em>,
                        <em class="parameter"><code>unsigned <span class="type">int</span> num_coords</code></em>,
@@ -247,8 +256,8 @@ hb_shape_plan_create2 (<em class="parameter"><code><a class="link" href="harfbuz
 <a name="hb-shape-plan-create-cached2"></a><h3>hb_shape_plan_create_cached2 ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="returnvalue">hb_shape_plan_t</span></a> *
 hb_shape_plan_create_cached2 (<em class="parameter"><code><a class="link" href="harfbuzz-hb-face.html#hb-face-t"><span class="type">hb_face_t</span></a> *face</code></em>,
-                              <em class="parameter"><code>const <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
-                              <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
+                              <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-buffer.html#hb-segment-properties-t"><span class="type">hb_segment_properties_t</span></a> *props</code></em>,
+                              <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *user_features</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> num_user_features</code></em>,
                               <em class="parameter"><code>const <span class="type">int</span> *coords</code></em>,
                               <em class="parameter"><code>unsigned <span class="type">int</span> num_coords</code></em>,
@@ -283,8 +292,8 @@ hb_shape_plan_destroy (<em class="parameter"><code><a class="link" href="harfbuz
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 hb_shape_plan_execute (<em class="parameter"><code><a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"><span class="type">hb_shape_plan_t</span></a> *shape_plan</code></em>,
                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
-                       <em class="parameter"><code><a class="link" href="harfbuzz-Buffers.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
-                       <em class="parameter"><code>const <a class="link" href="harfbuzz-Shaping.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
+                       <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+                       <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
                        <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>);</pre>
 <div class="refsect3">
 <a name="hb-shape-plan-execute.parameters"></a><h4>Parameters</h4>
@@ -454,6 +463,6 @@ hb_shape_plan_set_user_data (<em class="parameter"><code><a class="link" href="h
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb-shape.html b/docs/html/harfbuzz-hb-shape.html
new file mode 100644 (file)
index 0000000..b26887c
--- /dev/null
@@ -0,0 +1,367 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>hb-shape: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-shape-plan.html" title="hb-shape-plan">
+<link rel="next" href="harfbuzz-hb-unicode.html" title="hb-unicode">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-shape.description" class="shortcut">Description</a></span><span id="nav_hierarchy">  <span class="dim">|</span> 
+                  <a href="#harfbuzz-hb-shape.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-shape-plan.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-unicode.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="harfbuzz-hb-shape"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="harfbuzz-hb-shape.top_of_page"></a>hb-shape</span></h2>
+<p>hb-shape — Conversion of text strings into positioned glyphs</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-from-string" title="hb_feature_from_string ()">hb_feature_from_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-shape.html#hb-feature-to-string" title="hb_feature_to_string ()">hb_feature_to_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()">hb_shape</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-full" title="hb_shape_full ()">hb_shape_full</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">char</span> **
+</td>
+<td class="function_name">
+<a class="link" href="harfbuzz-hb-shape.html#hb-shape-list-shapers" title="hb_shape_list_shapers ()">hb_shape_list_shapers</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<a name="hb-feature-t"></a><div class="refsect1">
+<a name="harfbuzz-hb-shape.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-END:CAPS" title="HB_FEATURE_GLOBAL_END">HB_FEATURE_GLOBAL_END</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-START:CAPS" title="HB_FEATURE_GLOBAL_START">HB_FEATURE_GLOBAL_START</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-shape.html#hb-feature-t-struct" title="hb_feature_t">hb_feature_t</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+    <span class="lineart">╰──</span> hb_feature_t
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.description"></a><h2>Description</h2>
+<p>Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
+which are sequences of Unicode characters that use the same font and have
+the same text direction, script, and language. After shaping the buffer
+contains the output glyphs and their positions.</p>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="hb-feature-from-string"></a><h3>hb_feature_from_string ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_feature_from_string (<em class="parameter"><code>const <span class="type">char</span> *str</code></em>,
+                        <em class="parameter"><code><span class="type">int</span> len</code></em>,
+                        <em class="parameter"><code><a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *feature</code></em>);</pre>
+<p>Parses a string into a <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a>.</p>
+<p>TODO: document the syntax here.</p>
+<div class="refsect3">
+<a name="hb-feature-from-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>str</p></td>
+<td class="parameter_description"><p> a string to parse. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=len][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint8_t]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>length of <em class="parameter"><code>str</code></em>
+, or -1 if string is <code class="literal">NULL</code> terminated</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>feature</p></td>
+<td class="parameter_description"><p> the <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> to initialize with the parsed values. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-feature-from-string.returns"></a><h4>Returns</h4>
+<p><code class="literal">true</code> if <em class="parameter"><code>str</code></em>
+is successfully parsed, <code class="literal">false</code> otherwise.</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-feature-to-string"></a><h3>hb_feature_to_string ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_feature_to_string (<em class="parameter"><code><a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *feature</code></em>,
+                      <em class="parameter"><code><span class="type">char</span> *buf</code></em>,
+                      <em class="parameter"><code>unsigned <span class="type">int</span> size</code></em>);</pre>
+<p>Converts a <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> into a <code class="literal">NULL</code>-terminated string in the format
+understood by <a class="link" href="harfbuzz-hb-shape.html#hb-feature-from-string" title="hb_feature_from_string ()"><code class="function">hb_feature_from_string()</code></a>. The client in responsible for
+allocating big enough size for <em class="parameter"><code>buf</code></em>
+, 128 bytes is more than enough.</p>
+<div class="refsect3">
+<a name="hb-feature-to-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>feature</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> to convert</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p> output string. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=size][<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>size</p></td>
+<td class="parameter_description"><p>the allocated size of <em class="parameter"><code>buf</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-5.html#api-index-0.9.5">0.9.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-shape"></a><h3>hb_shape ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+hb_shape (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+          <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+          <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
+          <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>);</pre>
+<p>Shapes <em class="parameter"><code>buffer</code></em>
+ using <em class="parameter"><code>font</code></em>
+ turning its Unicode characters content to
+positioned glyphs. If <em class="parameter"><code>features</code></em>
+ is not <code class="literal">NULL</code>, it will be used to control the
+features applied during shaping.</p>
+<div class="refsect3">
+<a name="hb-shape.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> to use for shaping</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to shape</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>features</p></td>
+<td class="parameter_description"><p> an array of user
+specified <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> or <code class="literal">NULL</code>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=num_features][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>num_features</p></td>
+<td class="parameter_description"><p>the length of <em class="parameter"><code>features</code></em>
+array</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-shape-full"></a><h3>hb_shape_full ()</h3>
+<pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
+hb_shape_full (<em class="parameter"><code><a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> *font</code></em>,
+               <em class="parameter"><code><a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> *buffer</code></em>,
+               <em class="parameter"><code>const <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> *features</code></em>,
+               <em class="parameter"><code>unsigned <span class="type">int</span> num_features</code></em>,
+               <em class="parameter"><code>const <span class="type">char</span> * const *shaper_list</code></em>);</pre>
+<p>See <a class="link" href="harfbuzz-hb-shape.html#hb-shape" title="hb_shape ()"><code class="function">hb_shape()</code></a> for details. If <em class="parameter"><code>shaper_list</code></em>
+ is not <code class="literal">NULL</code>, the specified
+shapers will be used in the given order, otherwise the default shapers list
+will be used.</p>
+<div class="refsect3">
+<a name="hb-shape-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>font</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-font.html#hb-font-t"><span class="type">hb_font_t</span></a> to use for shaping</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>an <a class="link" href="harfbuzz-hb-buffer.html#hb-buffer-t"><span class="type">hb_buffer_t</span></a> to shape</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>features</p></td>
+<td class="parameter_description"><p> an array of user
+specified <a class="link" href="harfbuzz-hb-shape.html#hb-feature-t"><span class="type">hb_feature_t</span></a> or <code class="literal">NULL</code>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=num_features][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>num_features</p></td>
+<td class="parameter_description"><p>the length of <em class="parameter"><code>features</code></em>
+array</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>shaper_list</p></td>
+<td class="parameter_description"><p> a <code class="literal">NULL</code>-terminated
+array of shapers to use or <code class="literal">NULL</code>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> zero-terminated=1][<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="hb-shape-full.returns"></a><h4>Returns</h4>
+<p> false if all shapers failed, true otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-shape-list-shapers"></a><h3>hb_shape_list_shapers ()</h3>
+<pre class="programlisting">const <span class="returnvalue">char</span> **
+hb_shape_list_shapers (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Retrieves the list of shapers supported by HarfBuzz.</p>
+<div class="refsect3">
+<a name="hb-shape-list-shapers.returns"></a><h4>Returns</h4>
+<p> an array of
+constant strings. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>][<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> zero-terminated=1]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="harfbuzz-hb-shape.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="HB-FEATURE-GLOBAL-END:CAPS"></a><h3>HB_FEATURE_GLOBAL_END</h3>
+<pre class="programlisting">#define HB_FEATURE_GLOBAL_END ((unsigned int) -1)
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="HB-FEATURE-GLOBAL-START:CAPS"></a><h3>HB_FEATURE_GLOBAL_START</h3>
+<pre class="programlisting">#define HB_FEATURE_GLOBAL_START 0
+</pre>
+<p class="since">Since: <a class="link" href="api-index-2-0-0.html#api-index-2.0.0">2.0.0</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="hb-feature-t-struct"></a><h3>hb_feature_t</h3>
+<pre class="programlisting">typedef struct {
+  hb_tag_t      tag;
+  uint32_t      value;
+  unsigned int  start;
+  unsigned int  end;
+} hb_feature_t;
+</pre>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index e2bc935..97f93ab 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-unicode: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-common.html" title="hb-common">
-<link rel="next" href="harfbuzz-Buffers.html" title="Buffers">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-shape.html" title="hb-shape">
+<link rel="next" href="harfbuzz-hb-version.html" title="hb-version">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-unicode.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-common.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-Buffers.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-shape.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="harfbuzz-hb-version.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-unicode"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-unicode.top_of_page"></a>hb-unicode</span></h2>
-<p>hb-unicode</p>
+<p>hb-unicode — Unicode character property access</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </td>
 </tr>
 <tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-decompose-compatibility" title="hb_unicode_decompose_compatibility ()">hb_unicode_decompose_compatibility</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
 <td class="function_type">
 <a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 </td>
 </td>
 </tr>
 <tr>
-<td class="function_type">unsigned <span class="returnvalue">int</span>
-</td>
-<td class="function_name">
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-eastasian-width" title="hb_unicode_eastasian_width ()">hb_unicode_eastasian_width</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
 <td class="function_type">
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
 </td>
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-compatibility-func" title="hb_unicode_funcs_set_decompose_compatibility_func ()">hb_unicode_funcs_set_decompose_compatibility_func</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-func" title="hb_unicode_funcs_set_decompose_func ()">hb_unicode_funcs_set_decompose_func</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <span class="returnvalue">void</span>
 </td>
 <td class="function_name">
-<a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-eastasian-width-func" title="hb_unicode_funcs_set_eastasian_width_func ()">hb_unicode_funcs_set_eastasian_width_func</a> <span class="c_punctuation">()</span>
-</td>
-</tr>
-<tr>
-<td class="function_type">
-<span class="returnvalue">void</span>
-</td>
-<td class="function_name">
 <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-general-category-func" title="hb_unicode_funcs_set_general_category_func ()">hb_unicode_funcs_set_general_category_func</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
 <tbody>
 <tr>
 <td class="define_keyword">#define</td>
-<td class="function_name"><a class="link" href="harfbuzz-hb-unicode.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" title="HB_UNICODE_MAX_DECOMPOSITION_LEN">HB_UNICODE_MAX_DECOMPOSITION_LEN</a></td>
+<td class="function_name"><a class="link" href="harfbuzz-hb-unicode.html#HB-UNICODE-MAX:CAPS" title="HB_UNICODE_MAX">HB_UNICODE_MAX</a></td>
 </tr>
 <tr>
 <td class="datatype_keyword">enum</td>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-unicode.object-hierarchy"></a><h2>Object Hierarchy</h2>
-<pre class="screen">    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+<pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> hb_unicode_funcs_t
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">├──</span> hb_unicode_combining_class_t
     <span class="lineart">╰──</span> hb_unicode_general_category_t
 </pre>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-unicode.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-unicode.description"></a><h2>Description</h2>
+<p>Unicode functions are used to access Unicode character properties.
+Client can pass its own Unicode functions to HarfBuzz, or access
+the built-in Unicode functions that come with HarfBuzz.</p>
+<p>With the Unicode functions, one can query variour Unicode character
+properties, such as General Category, Script, Combining Class, etc.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-unicode.functions_details"></a><h2>Functions</h2>
@@ -434,37 +414,6 @@ hb_unicode_decompose (<em class="parameter"><code><a class="link" href="harfbuzz
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-unicode-decompose-compatibility"></a><h3>hb_unicode_decompose_compatibility ()</h3>
-<pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_unicode_decompose_compatibility (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
-                                    <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> u</code></em>,
-                                    <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> *decomposed</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-unicode-decompose-compatibility.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>ufuncs</p></td>
-<td class="parameter_description"><p>Unicode functions.</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>decomposed</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-unicode-decompose-func-t"></a><h3>hb_unicode_decompose_func_t ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-common.html#hb-bool-t" title="hb_bool_t"><span class="returnvalue">hb_bool_t</span></a>
 <span class="c_punctuation">(</span>*hb_unicode_decompose_func_t<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
@@ -475,14 +424,6 @@ hb_unicode_decompose_compatibility (<em class="parameter"><code><a class="link"
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-unicode-eastasian-width"></a><h3>hb_unicode_eastasian_width ()</h3>
-<pre class="programlisting">unsigned <span class="returnvalue">int</span>
-hb_unicode_eastasian_width (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
-                            <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-codepoint-t" title="hb_codepoint_t"><span class="type">hb_codepoint_t</span></a> unicode</code></em>);</pre>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-unicode-funcs-create"></a><h3>hb_unicode_funcs_create ()</h3>
 <pre class="programlisting"><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="returnvalue">hb_unicode_funcs_t</span></a> *
 hb_unicode_funcs_create (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *parent</code></em>);</pre>
@@ -740,39 +681,6 @@ hb_unicode_funcs_set_compose_func (<em class="parameter"><code><a class="link" h
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-unicode-funcs-set-decompose-compatibility-func"></a><h3>hb_unicode_funcs_set_decompose_compatibility_func ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_unicode_funcs_set_decompose_compatibility_func
-                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
-                                <em class="parameter"><code><span class="type">hb_unicode_decompose_compatibility_func_t</span> func</code></em>,
-                                <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-unicode-funcs-set-decompose-compatibility-func.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>ufuncs</p></td>
-<td class="parameter_description"><p>a Unicode function structure</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>func</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-unicode-funcs-set-decompose-func"></a><h3>hb_unicode_funcs_set_decompose_func ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_unicode_funcs_set_decompose_func (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
@@ -805,39 +713,6 @@ hb_unicode_funcs_set_decompose_func (<em class="parameter"><code><a class="link"
 </div>
 <hr>
 <div class="refsect2">
-<a name="hb-unicode-funcs-set-eastasian-width-func"></a><h3>hb_unicode_funcs_set_eastasian_width_func ()</h3>
-<pre class="programlisting"><span class="returnvalue">void</span>
-hb_unicode_funcs_set_eastasian_width_func
-                               (<em class="parameter"><code><a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"><span class="type">hb_unicode_funcs_t</span></a> *ufuncs</code></em>,
-                                <em class="parameter"><code><span class="type">hb_unicode_eastasian_width_func_t</span> func</code></em>,
-                                <em class="parameter"><code><span class="type">void</span> *user_data</code></em>,
-                                <em class="parameter"><code><a class="link" href="harfbuzz-hb-common.html#hb-destroy-func-t" title="hb_destroy_func_t ()"><span class="type">hb_destroy_func_t</span></a> destroy</code></em>);</pre>
-<div class="refsect3">
-<a name="hb-unicode-funcs-set-eastasian-width-func.parameters"></a><h4>Parameters</h4>
-<div class="informaltable"><table class="informaltable" width="100%" border="0">
-<colgroup>
-<col width="150px" class="parameters_name">
-<col class="parameters_description">
-<col width="200px" class="parameters_annotations">
-</colgroup>
-<tbody>
-<tr>
-<td class="parameter_name"><p>ufuncs</p></td>
-<td class="parameter_description"><p>a Unicode function structure</p></td>
-<td class="parameter_annotations"> </td>
-</tr>
-<tr>
-<td class="parameter_name"><p>func</p></td>
-<td class="parameter_description"><p>. </p></td>
-<td class="parameter_annotations"><span class="annotation">[<acronym title="This parameter is a 'user_data', for callbacks; many bindings can pass NULL here."><span class="acronym">closure</span></acronym> user_data][<acronym title="This parameter is a 'destroy_data', for callbacks."><span class="acronym">destroy</span></acronym> destroy][<acronym title="The callback is valid until the GDestroyNotify argument is called."><span class="acronym">scope notified</span></acronym>]</span></td>
-</tr>
-</tbody>
-</table></div>
-</div>
-<p class="since">Since: <a class="link" href="api-index-0-9-2.html#api-index-0.9.2">0.9.2</a></p>
-</div>
-<hr>
-<div class="refsect2">
 <a name="hb-unicode-funcs-set-general-category-func"></a><h3>hb_unicode_funcs_set_general_category_func ()</h3>
 <pre class="programlisting"><span class="returnvalue">void</span>
 hb_unicode_funcs_set_general_category_func
@@ -1012,9 +887,10 @@ hb_unicode_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb
 <div class="refsect1">
 <a name="harfbuzz-hb-unicode.other_details"></a><h2>Types and Values</h2>
 <div class="refsect2">
-<a name="HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS"></a><h3>HB_UNICODE_MAX_DECOMPOSITION_LEN</h3>
-<pre class="programlisting">#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
+<a name="HB-UNICODE-MAX:CAPS"></a><h3>HB_UNICODE_MAX</h3>
+<pre class="programlisting">#define HB_UNICODE_MAX 0x10FFFFu
 </pre>
+<p class="since">Since: <a class="link" href="api-index-1-9-0.html#api-index-1.9.0">1.9.0</a></p>
 </div>
 <hr>
 <div class="refsect2">
@@ -1492,6 +1368,6 @@ hb_unicode_script (<em class="parameter"><code><a class="link" href="harfbuzz-hb
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 3d1d4d0..425ef7e 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-uniscribe: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-hb-graphite2.html" title="hb-graphite2">
-<link rel="next" href="harfbuzz-hb-coretext.html" title="hb-coretext">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch12.html" title="Integration API">
+<link rel="prev" href="harfbuzz-hb-icu.html" title="hb-icu">
+<link rel="next" href="api-index-full.html" title="API Index">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-uniscribe.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-graphite2.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-coretext.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch12.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-icu.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-full.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-uniscribe"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-uniscribe.top_of_page"></a>hb-uniscribe</span></h2>
-<p>hb-uniscribe</p>
+<p>hb-uniscribe — Windows integration</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-uniscribe.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb-uniscribe.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-uniscribe.description"></a><h2>Description</h2>
+<p>Functions for using HarfBuzz with the Windows fonts.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-uniscribe.functions_details"></a><h2>Functions</h2>
@@ -80,6 +86,6 @@ hb_uniscribe_font_get_logfontw (<em class="parameter"><code><a class="link" href
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 3180c50..00569c9 100644 (file)
@@ -5,10 +5,10 @@
 <title>hb-version: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="harfbuzz-Shaping.html" title="Shaping">
-<link rel="next" href="harfbuzz-hb-deprecated.html" title="hb-deprecated">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="up" href="ch09.html" title="Core API">
+<link rel="prev" href="harfbuzz-hb-unicode.html" title="hb-unicode">
+<link rel="next" href="ch10.html" title="OpenType API">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
                   <a href="#harfbuzz-hb-version.description" class="shortcut">Description</a></span>
 </td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-Shaping.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-deprecated.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="u" href="ch09.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="harfbuzz-hb-unicode.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch10.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="refentry">
 <a name="harfbuzz-hb-version"></a><div class="titlepage"></div>
 <div class="refnamediv"><table width="100%"><tr>
 <td valign="top">
 <h2><span class="refentrytitle"><a name="harfbuzz-hb-version.top_of_page"></a>hb-version</span></h2>
-<p>hb-version</p>
+<p>hb-version — Information about the version of HarfBuzz in use</p>
 </td>
 <td class="gallery_image" valign="top" align="right"></td>
 </tr></table></div>
 </table></div>
 </div>
 <div class="refsect1">
+<a name="harfbuzz-hb-version.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include &lt;hb.h&gt;
+</pre>
+</div>
+<div class="refsect1">
 <a name="harfbuzz-hb-version.description"></a><h2>Description</h2>
+<p>These functions and macros allow accessing version of the HarfBuzz
+library used at compile- as well as run-time, and to direct code
+conditionally based on those versions, again, at compile- or run-time.</p>
 </div>
 <div class="refsect1">
 <a name="harfbuzz-hb-version.functions_details"></a><h2>Functions</h2>
@@ -126,17 +134,17 @@ hb_version (<em class="parameter"><code>unsigned <span class="type">int</span> *
 <tbody>
 <tr>
 <td class="parameter_name"><p>major</p></td>
-<td class="parameter_description"><p>Library major version component. </p></td>
+<td class="parameter_description"><p> Library major version component. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 <tr>
 <td class="parameter_name"><p>minor</p></td>
-<td class="parameter_description"><p>Library minor version component. </p></td>
+<td class="parameter_description"><p> Library minor version component. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 <tr>
 <td class="parameter_name"><p>micro</p></td>
-<td class="parameter_description"><p>Library micro version component. </p></td>
+<td class="parameter_description"><p> Library micro version component. </p></td>
 <td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter for returning results. Default is transfer full."><span class="acronym">out</span></acronym>]</span></td>
 </tr>
 </tbody>
@@ -170,7 +178,7 @@ hb_version_string (<em class="parameter"><code><span class="type">void</span></c
 <a name="harfbuzz-hb-version.other_details"></a><h2>Types and Values</h2>
 <div class="refsect2">
 <a name="HB-VERSION-MAJOR:CAPS"></a><h3>HB_VERSION_MAJOR</h3>
-<pre class="programlisting">#define HB_VERSION_MAJOR 1
+<pre class="programlisting">#define HB_VERSION_MAJOR 2
 </pre>
 </div>
 <hr>
@@ -182,18 +190,18 @@ hb_version_string (<em class="parameter"><code><span class="type">void</span></c
 <hr>
 <div class="refsect2">
 <a name="HB-VERSION-MINOR:CAPS"></a><h3>HB_VERSION_MINOR</h3>
-<pre class="programlisting">#define HB_VERSION_MINOR 8
+<pre class="programlisting">#define HB_VERSION_MINOR 3
 </pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="HB-VERSION-STRING:CAPS"></a><h3>HB_VERSION_STRING</h3>
-<pre class="programlisting">#define HB_VERSION_STRING "1.8.1"
+<pre class="programlisting">#define HB_VERSION_STRING "2.3.1"
 </pre>
 </div>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/harfbuzz-hb.html b/docs/html/harfbuzz-hb.html
deleted file mode 100644 (file)
index 6089a9e..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>hb: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="ch08.html" title="HarfBuzz API">
-<link rel="prev" href="ch08.html" title="HarfBuzz API">
-<link rel="next" href="harfbuzz-hb-common.html" title="hb-common">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts">
-<a href="#" class="shortcut">Top</a><span id="nav_description">  <span class="dim">|</span> 
-                  <a href="#harfbuzz-hb.description" class="shortcut">Description</a></span>
-</td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="ch08.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="ch08.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="harfbuzz-hb-common.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="refentry">
-<a name="harfbuzz-hb"></a><div class="titlepage"></div>
-<div class="refnamediv"><table width="100%"><tr>
-<td valign="top">
-<h2><span class="refentrytitle"><a name="harfbuzz-hb.top_of_page"></a>hb</span></h2>
-<p>hb</p>
-</td>
-<td class="gallery_image" valign="top" align="right"></td>
-</tr></table></div>
-<div class="refsect1">
-<a name="harfbuzz-hb.description"></a><h2>Description</h2>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb.functions_details"></a><h2>Functions</h2>
-<p></p>
-</div>
-<div class="refsect1">
-<a name="harfbuzz-hb.other_details"></a><h2>Types and Values</h2>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
index c4ed6ff..ccfc846 100644 (file)
@@ -3,15 +3,35 @@
   <chapters>
     <sub name="User's manual" link="pt01.html">
       <sub name="What is HarfBuzz?" link="what-is-harfbuzz.html">
-        <sub name="Why do I need it?" link="what-is-harfbuzz.html#why-do-i-need-it"/>
+        <sub name="What is text shaping?" link="what-is-harfbuzz.html#what-is-text-shaping"/>
+        <sub name="Why do I need a shaping engine?" link="why-do-i-need-a-shaping-engine.html"/>
+        <sub name="What does HarfBuzz do?" link="ch01s03.html"/>
+        <sub name="What HarfBuzz doesn't do" link="what-harfbuzz-doesnt-do.html"/>
         <sub name="Why is it called HarfBuzz?" link="why-is-it-called-harfbuzz.html"/>
       </sub>
-      <sub name="Install HarfBuzz" link="install-harfbuzz.html">
-        <sub name="Download" link="install-harfbuzz.html#download"/>
-        <sub name="Building" link="building.html"/>
+      <sub name="Installing HarfBuzz" link="install-harfbuzz.html">
+        <sub name="Downloading HarfBuzz" link="install-harfbuzz.html#download"/>
+        <sub name="Building HarfBuzz" link="building.html">
+          <sub name="Building on Linux" link="building.html#building.linux"/>
+          <sub name="Building on Windows" link="building.html#building.windows"/>
+          <sub name="Building on macOS" link="building.html#building.macos"/>
+          <sub name="Configuration options" link="building.html#configuration"/>
+        </sub>
       </sub>
-      <sub name="Hello, HarfBuzz" link="hello-harfbuzz.html">
-        <sub name="What HarfBuzz doesn't do" link="hello-harfbuzz.html#what-harfbuzz-doesnt-do"/>
+      <sub name="Getting started with HarfBuzz" link="getting-started.html">
+        <sub name="An overview of the HarfBuzz shaping API" link="getting-started.html#id-1.2.4.2"/>
+        <sub name="Terminology" link="ch03s02.html"/>
+        <sub name="A simple shaping example" link="ch03s03.html"/>
+      </sub>
+      <sub name="Shaping concepts" link="shaping-concepts.html">
+        <sub name="Text shaping" link="shaping-concepts.html#text-shaping-concepts"/>
+        <sub name="Complex scripts" link="complex-scripts.html"/>
+        <sub name="Shaping operations" link="shaping-operations.html"/>
+        <sub name="Unicode character categories" link="unicode-character-categories.html"/>
+        <sub name="Text runs" link="text-runs.html"/>
+        <sub name="OpenType shaping models" link="opentype-shaping-models.html"/>
+        <sub name="Graphite shaping" link="graphite-shaping.html"/>
+        <sub name="AAT shaping" link="aat-shaping.html"/>
       </sub>
       <sub name="Buffers, language, script and direction" link="buffers-language-script-and-direction.html">
         <sub name="Creating and destroying buffers" link="buffers-language-script-and-direction.html#creating-and-destroying-buffers"/>
         <sub name="Using HarfBuzz's native OpenType implementation" link="using-harfbuzzs-native-opentype-implementation.html"/>
         <sub name="Using your own font functions" link="using-your-own-font-functions.html"/>
       </sub>
-      <sub name="" link="clusters.html">
-        <sub name="Clusters" link="clusters.html#clusters"/>
+      <sub name="Clusters" link="clusters.html">
+        <sub name="Clusters and shaping" link="clusters.html#clusters-and-shaping"/>
+        <sub name="Working with HarfBuzz clusters" link="working-with-harfbuzz-clusters.html"/>
         <sub name="A clustering example for levels 0 and 1" link="a-clustering-example-for-levels-0-and-1.html"/>
         <sub name="Reordering in levels 0 and 1" link="reordering-in-levels-0-and-1.html"/>
         <sub name="The distinction between levels 0 and 1" link="the-distinction-between-levels-0-and-1.html"/>
-        <sub name="Level 2" link="level-2.html"/>
+        <sub name="Level 2" link="level-2.html">
+          <sub name="Ligatures with combining marks in level 2" link="level-2.html#ligatures-with-combining-marks-in-level-2"/>
+          <sub name="Reordering in level 2" link="level-2.html#reordering-in-level-2"/>
+          <sub name="Other considerations in level 2" link="level-2.html#other-considerations-in-level-2"/>
+        </sub>
       </sub>
       <sub name="Shaping and shape plans" link="shaping-and-shape-plans.html">
         <sub name="OpenType features" link="shaping-and-shape-plans.html#opentype-features"/>
       <sub name="Glyph information" link="pt01.html#glyph-information"/>
     </sub>
     <sub name="Reference manual" link="pt02.html">
-      <sub name="HarfBuzz API" link="ch08.html">
-        <sub name="hb" link="harfbuzz-hb.html"/>
-        <sub name="hb-common" link="harfbuzz-hb-common.html"/>
-        <sub name="hb-unicode" link="harfbuzz-hb-unicode.html"/>
-        <sub name="Buffers" link="harfbuzz-Buffers.html"/>
+      <sub name="Core API" link="ch09.html">
         <sub name="hb-blob" link="harfbuzz-hb-blob.html"/>
+        <sub name="hb-buffer" link="harfbuzz-hb-buffer.html"/>
+        <sub name="hb-common" link="harfbuzz-hb-common.html"/>
+        <sub name="hb-deprecated" link="harfbuzz-hb-deprecated.html"/>
         <sub name="hb-face" link="harfbuzz-hb-face.html"/>
         <sub name="hb-font" link="harfbuzz-hb-font.html"/>
-        <sub name="Shaping" link="harfbuzz-Shaping.html"/>
-        <sub name="hb-version" link="harfbuzz-hb-version.html"/>
-        <sub name="hb-deprecated" link="harfbuzz-hb-deprecated.html"/>
+        <sub name="hb-map" link="harfbuzz-hb-map.html"/>
         <sub name="hb-set" link="harfbuzz-hb-set.html"/>
-        <sub name="hb-ot" link="harfbuzz-hb-ot.html"/>
-        <sub name="hb-ot-layout" link="harfbuzz-hb-ot-layout.html"/>
-        <sub name="hb-ot-tag" link="harfbuzz-hb-ot-tag.html"/>
+        <sub name="hb-shape-plan" link="harfbuzz-hb-shape-plan.html"/>
+        <sub name="hb-shape" link="harfbuzz-hb-shape.html"/>
+        <sub name="hb-unicode" link="harfbuzz-hb-unicode.html"/>
+        <sub name="hb-version" link="harfbuzz-hb-version.html"/>
+      </sub>
+      <sub name="OpenType API" link="ch10.html">
+        <sub name="hb-ot-color" link="harfbuzz-hb-ot-color.html"/>
         <sub name="hb-ot-font" link="harfbuzz-hb-ot-font.html"/>
-        <sub name="hb-ot-shape" link="harfbuzz-hb-ot-shape.html"/>
+        <sub name="hb-ot-layout" link="harfbuzz-hb-ot-layout.html"/>
         <sub name="hb-ot-math" link="harfbuzz-hb-ot-math.html"/>
-        <sub name="hb-shape-plan" link="harfbuzz-hb-shape-plan.html"/>
-        <sub name="hb-glib" link="harfbuzz-hb-glib.html"/>
-        <sub name="hb-icu" link="harfbuzz-hb-icu.html"/>
+        <sub name="hb-ot-name" link="harfbuzz-hb-ot-name.html"/>
+        <sub name="hb-ot-shape" link="harfbuzz-hb-ot-shape.html"/>
+        <sub name="hb-ot-var" link="harfbuzz-hb-ot-var.html"/>
+      </sub>
+      <sub name="Apple Advanced Typography API" link="ch11.html">
+        <sub name="hb-aat-layout" link="harfbuzz-hb-aat-layout.html"/>
+      </sub>
+      <sub name="Integration API" link="ch12.html">
+        <sub name="hb-coretext" link="harfbuzz-hb-coretext.html"/>
         <sub name="hb-ft" link="harfbuzz-hb-ft.html"/>
+        <sub name="hb-glib" link="harfbuzz-hb-glib.html"/>
+        <sub name="hb-gobject" link="harfbuzz-hb-gobject.html"/>
         <sub name="hb-graphite2" link="harfbuzz-hb-graphite2.html"/>
+        <sub name="hb-icu" link="harfbuzz-hb-icu.html"/>
         <sub name="hb-uniscribe" link="harfbuzz-hb-uniscribe.html"/>
-        <sub name="hb-coretext" link="harfbuzz-hb-coretext.html"/>
-        <sub name="hb-gobject" link="harfbuzz-hb-gobject.html"/>
       </sub>
-      <sub name="Object Hierarchy" link="object-tree.html"/>
       <sub name="API Index" link="api-index-full.html"/>
-      <sub name="Index of new symbols in 0.9.2" link="api-index-0-9-2.html"/>
-      <sub name="Index of new symbols in 0.9.5" link="api-index-0-9-5.html"/>
-      <sub name="Index of new symbols in 0.9.7" link="api-index-0-9-7.html"/>
-      <sub name="Index of new symbols in 0.9.8" link="api-index-0-9-8.html"/>
-      <sub name="Index of new symbols in 0.9.10" link="api-index-0-9-10.html"/>
-      <sub name="Index of new symbols in 0.9.11" link="api-index-0-9-11.html"/>
-      <sub name="Index of new symbols in 0.9.20" link="api-index-0-9-20.html"/>
-      <sub name="Index of new symbols in 0.9.22" link="api-index-0-9-22.html"/>
-      <sub name="Index of new symbols in 0.9.28" link="api-index-0-9-28.html"/>
-      <sub name="Index of new symbols in 0.9.30" link="api-index-0-9-30.html"/>
-      <sub name="Index of new symbols in 0.9.31" link="api-index-0-9-31.html"/>
-      <sub name="Index of new symbols in 0.9.38" link="api-index-0-9-38.html"/>
-      <sub name="Index of new symbols in 0.9.39" link="api-index-0-9-39.html"/>
-      <sub name="Index of new symbols in 0.9.41" link="api-index-0-9-41.html"/>
-      <sub name="Index of new symbols in 0.9.42" link="api-index-0-9-42.html"/>
-      <sub name="Index of new symbols in 1.0.5" link="api-index-1-0-5.html"/>
-      <sub name="Index of new symbols in 1.1.2" link="api-index-1-1-2.html"/>
-      <sub name="Index of new symbols in 1.1.3" link="api-index-1-1-3.html"/>
-      <sub name="Index of new symbols in 1.2.3" link="api-index-1-2-3.html"/>
-      <sub name="Index of new symbols in 1.3.3" link="api-index-1-3-3.html"/>
-      <sub name="Index of new symbols in 1.4.2" link="api-index-1-4-2.html"/>
-      <sub name="Index of new symbols in 1.4.3" link="api-index-1-4-3.html"/>
-      <sub name="Index of new symbols in 1.5.0" link="api-index-1-5-0.html"/>
-      <sub name="Index of new symbols in 1.6.0" link="api-index-1-6-0.html"/>
       <sub name="Index of deprecated API" link="deprecated-api-index.html"/>
+      <sub name="Index of new symbols in 2.1.0" link="api-index-2-1-0.html"/>
+      <sub name="Index of new symbols in 2.0.0" link="api-index-2-0-0.html"/>
+      <sub name="Index of new symbols in 1.9.0" link="api-index-1-9-0.html"/>
+      <sub name="Index of new symbols in 1.8.6" link="api-index-1-8-6.html"/>
+      <sub name="Index of new symbols in 1.8.5" link="api-index-1-8-5.html"/>
+      <sub name="Index of new symbols in 1.8.1" link="api-index-1-8-1.html"/>
+      <sub name="Index of new symbols in 1.8.0" link="api-index-1-8-0.html"/>
+      <sub name="Index of new symbols in 1.7.7" link="api-index-1-7-7.html"/>
+      <sub name="Index of new symbols in 1.7.5" link="api-index-1-7-5.html"/>
+      <sub name="Index of new symbols in 1.6.0" link="api-index-1-6-0.html"/>
+      <sub name="Index of new symbols in 1.5.0" link="api-index-1-5-0.html"/>
+      <sub name="Index of new symbols in 1.4.3" link="api-index-1-4-3.html"/>
+      <sub name="Index of new symbols in 1.4.2" link="api-index-1-4-2.html"/>
+      <sub name="Index of new symbols in 1.4.0" link="api-index-1-4-0.html"/>
+      <sub name="Index of new symbols in 1.3.3" link="api-index-1-3-3.html"/>
+      <sub name="Index of new symbols in 1.2.3" link="api-index-1-2-3.html"/>
+      <sub name="Index of new symbols in 1.1.3" link="api-index-1-1-3.html"/>
+      <sub name="Index of new symbols in 1.1.2" link="api-index-1-1-2.html"/>
+      <sub name="Index of new symbols in 1.0.5" link="api-index-1-0-5.html"/>
+      <sub name="Index of new symbols in 0.9.42" link="api-index-0-9-42.html"/>
+      <sub name="Index of new symbols in 0.9.41" link="api-index-0-9-41.html"/>
+      <sub name="Index of new symbols in 0.9.39" link="api-index-0-9-39.html"/>
+      <sub name="Index of new symbols in 0.9.38" link="api-index-0-9-38.html"/>
+      <sub name="Index of new symbols in 0.9.31" link="api-index-0-9-31.html"/>
+      <sub name="Index of new symbols in 0.9.30" link="api-index-0-9-30.html"/>
+      <sub name="Index of new symbols in 0.9.28" link="api-index-0-9-28.html"/>
+      <sub name="Index of new symbols in 0.9.22" link="api-index-0-9-22.html"/>
+      <sub name="Index of new symbols in 0.9.20" link="api-index-0-9-20.html"/>
+      <sub name="Index of new symbols in 0.9.11" link="api-index-0-9-11.html"/>
+      <sub name="Index of new symbols in 0.9.10" link="api-index-0-9-10.html"/>
+      <sub name="Index of new symbols in 0.9.8" link="api-index-0-9-8.html"/>
+      <sub name="Index of new symbols in 0.9.7" link="api-index-0-9-7.html"/>
+      <sub name="Index of new symbols in 0.9.5" link="api-index-0-9-5.html"/>
+      <sub name="Index of new symbols in 0.9.2" link="api-index-0-9-2.html"/>
       <sub name="Annotation Glossary" link="annotation-glossary.html"/>
     </sub>
   </chapters>
   <functions>
+    <keyword type="function" name="hb_blob_create ()" link="harfbuzz-hb-blob.html#hb-blob-create" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_create_from_file ()" link="harfbuzz-hb-blob.html#hb-blob-create-from-file" since="1.7.7"/>
+    <keyword type="function" name="hb_blob_create_sub_blob ()" link="harfbuzz-hb-blob.html#hb-blob-create-sub-blob" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_copy_writable_or_fail ()" link="harfbuzz-hb-blob.html#hb-blob-copy-writable-or-fail" since="1.8.0"/>
+    <keyword type="function" name="hb_blob_destroy ()" link="harfbuzz-hb-blob.html#hb-blob-destroy" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_get_data ()" link="harfbuzz-hb-blob.html#hb-blob-get-data" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_get_data_writable ()" link="harfbuzz-hb-blob.html#hb-blob-get-data-writable" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_get_empty ()" link="harfbuzz-hb-blob.html#hb-blob-get-empty" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_get_length ()" link="harfbuzz-hb-blob.html#hb-blob-get-length" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_get_user_data ()" link="harfbuzz-hb-blob.html#hb-blob-get-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_is_immutable ()" link="harfbuzz-hb-blob.html#hb-blob-is-immutable" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_make_immutable ()" link="harfbuzz-hb-blob.html#hb-blob-make-immutable" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_reference ()" link="harfbuzz-hb-blob.html#hb-blob-reference" since="0.9.2"/>
+    <keyword type="function" name="hb_blob_set_user_data ()" link="harfbuzz-hb-blob.html#hb-blob-set-user-data" since="0.9.2"/>
+    <keyword type="typedef" name="hb_blob_t" link="harfbuzz-hb-blob.html#hb-blob-t"/>
+    <keyword type="enum" name="enum hb_memory_mode_t" link="harfbuzz-hb-blob.html#hb-memory-mode-t"/>
+    <keyword type="function" name="hb_buffer_create ()" link="harfbuzz-hb-buffer.html#hb-buffer-create" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_reference ()" link="harfbuzz-hb-buffer.html#hb-buffer-reference" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_empty ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-empty" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_destroy ()" link="harfbuzz-hb-buffer.html#hb-buffer-destroy" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_reset ()" link="harfbuzz-hb-buffer.html#hb-buffer-reset" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_clear_contents ()" link="harfbuzz-hb-buffer.html#hb-buffer-clear-contents" since="0.9.11"/>
+    <keyword type="function" name="hb_buffer_pre_allocate ()" link="harfbuzz-hb-buffer.html#hb-buffer-pre-allocate" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_allocation_successful ()" link="harfbuzz-hb-buffer.html#hb-buffer-allocation-successful" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_add ()" link="harfbuzz-hb-buffer.html#hb-buffer-add" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_add_codepoints ()" link="harfbuzz-hb-buffer.html#hb-buffer-add-codepoints" since="0.9.31"/>
+    <keyword type="function" name="hb_buffer_add_utf32 ()" link="harfbuzz-hb-buffer.html#hb-buffer-add-utf32" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_add_utf16 ()" link="harfbuzz-hb-buffer.html#hb-buffer-add-utf16" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_add_utf8 ()" link="harfbuzz-hb-buffer.html#hb-buffer-add-utf8" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_add_latin1 ()" link="harfbuzz-hb-buffer.html#hb-buffer-add-latin1" since="0.9.39"/>
+    <keyword type="function" name="hb_buffer_append ()" link="harfbuzz-hb-buffer.html#hb-buffer-append" since="1.5.0"/>
+    <keyword type="function" name="hb_buffer_set_content_type ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-content-type" since="0.9.5"/>
+    <keyword type="function" name="hb_buffer_get_content_type ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-content-type" since="0.9.5"/>
+    <keyword type="function" name="hb_buffer_set_direction ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-direction" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_direction ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-direction" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_set_script ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-script" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_script ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-script" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_set_language ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-language" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_language ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-language" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_set_flags ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-flags" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_get_flags ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-flags" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_set_cluster_level ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-cluster-level" since="0.9.42"/>
+    <keyword type="function" name="hb_buffer_get_cluster_level ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-cluster-level" since="0.9.42"/>
+    <keyword type="function" name="hb_buffer_set_length ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-length" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_length ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-length" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_set_segment_properties ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-segment-properties" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_get_segment_properties ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-segment-properties" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_guess_segment_properties ()" link="harfbuzz-hb-buffer.html#hb-buffer-guess-segment-properties" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_set_unicode_funcs ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-unicode-funcs" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_unicode_funcs ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-unicode-funcs" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_set_user_data ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_user_data ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_glyph_infos ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-infos" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_glyph_positions ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-glyph-positions" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_get_invisible_glyph ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-invisible-glyph" since="2.0.0"/>
+    <keyword type="function" name="hb_buffer_set_invisible_glyph ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-invisible-glyph" since="2.0.0"/>
+    <keyword type="function" name="hb_buffer_set_replacement_codepoint ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-replacement-codepoint" since="0.9.31"/>
+    <keyword type="function" name="hb_buffer_get_replacement_codepoint ()" link="harfbuzz-hb-buffer.html#hb-buffer-get-replacement-codepoint" since="0.9.31"/>
+    <keyword type="function" name="hb_buffer_normalize_glyphs ()" link="harfbuzz-hb-buffer.html#hb-buffer-normalize-glyphs" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_reverse ()" link="harfbuzz-hb-buffer.html#hb-buffer-reverse" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_reverse_range ()" link="harfbuzz-hb-buffer.html#hb-buffer-reverse-range" since="0.9.41"/>
+    <keyword type="function" name="hb_buffer_reverse_clusters ()" link="harfbuzz-hb-buffer.html#hb-buffer-reverse-clusters" since="0.9.2"/>
+    <keyword type="function" name="hb_buffer_serialize_glyphs ()" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-glyphs" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_deserialize_glyphs ()" link="harfbuzz-hb-buffer.html#hb-buffer-deserialize-glyphs" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_serialize_format_from_string ()" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-from-string" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_serialize_format_to_string ()" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-to-string" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_serialize_list_formats ()" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-list-formats" since="0.9.7"/>
+    <keyword type="function" name="hb_segment_properties_equal ()" link="harfbuzz-hb-buffer.html#hb-segment-properties-equal" since="0.9.7"/>
+    <keyword type="function" name="hb_segment_properties_hash ()" link="harfbuzz-hb-buffer.html#hb-segment-properties-hash" since="0.9.7"/>
+    <keyword type="function" name="hb_buffer_diff ()" link="harfbuzz-hb-buffer.html#hb-buffer-diff" since="1.5.0"/>
+    <keyword type="function" name="hb_buffer_set_message_func ()" link="harfbuzz-hb-buffer.html#hb-buffer-set-message-func" since="1.1.3"/>
+    <keyword type="function" name="hb_glyph_info_get_glyph_flags ()" link="harfbuzz-hb-buffer.html#hb-glyph-info-get-glyph-flags" since="1.5.0"/>
+    <keyword type="function" name="hb_buffer_message_func_t ()" link="harfbuzz-hb-buffer.html#hb-buffer-message-func-t"/>
+    <keyword type="macro" name="HB_SEGMENT_PROPERTIES_DEFAULT" link="harfbuzz-hb-buffer.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS"/>
+    <keyword type="macro" name="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT" link="harfbuzz-hb-buffer.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" since="0.9.31"/>
+    <keyword type="typedef" name="hb_buffer_t" link="harfbuzz-hb-buffer.html#hb-buffer-t"/>
+    <keyword type="enum" name="enum hb_glyph_flags_t" link="harfbuzz-hb-buffer.html#hb-glyph-flags-t" since="1.5.0"/>
+    <keyword type="struct" name="hb_glyph_position_t" link="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct"/>
+    <keyword type="enum" name="enum hb_buffer_content_type_t" link="harfbuzz-hb-buffer.html#hb-buffer-content-type-t"/>
+    <keyword type="enum" name="enum hb_buffer_flags_t" link="harfbuzz-hb-buffer.html#hb-buffer-flags-t" since="0.9.20"/>
+    <keyword type="enum" name="enum hb_buffer_cluster_level_t" link="harfbuzz-hb-buffer.html#hb-buffer-cluster-level-t" since="0.9.42"/>
+    <keyword type="struct" name="hb_segment_properties_t" link="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct"/>
+    <keyword type="enum" name="enum hb_buffer_serialize_format_t" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-format-t" since="0.9.2"/>
+    <keyword type="enum" name="enum hb_buffer_serialize_flags_t" link="harfbuzz-hb-buffer.html#hb-buffer-serialize-flags-t" since="0.9.20"/>
+    <keyword type="enum" name="enum hb_buffer_diff_flags_t" link="harfbuzz-hb-buffer.html#hb-buffer-diff-flags-t"/>
     <keyword type="function" name="hb_tag_from_string ()" link="harfbuzz-hb-common.html#hb-tag-from-string" since="0.9.2"/>
     <keyword type="function" name="hb_tag_to_string ()" link="harfbuzz-hb-common.html#hb-tag-to-string" since="0.9.5"/>
     <keyword type="function" name="hb_direction_from_string ()" link="harfbuzz-hb-common.html#hb-direction-from-string" since="0.9.2"/>
     <keyword type="macro" name="HB_TAG_MAX" link="harfbuzz-hb-common.html#HB-TAG-MAX:CAPS"/>
     <keyword type="macro" name="HB_TAG_MAX_SIGNED" link="harfbuzz-hb-common.html#HB-TAG-MAX-SIGNED:CAPS"/>
     <keyword type="macro" name="HB_LANGUAGE_INVALID" link="harfbuzz-hb-common.html#HB-LANGUAGE-INVALID:CAPS"/>
-    <keyword type="function" name="hb_unicode_combining_class ()" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_combining_class_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class-func-t"/>
-    <keyword type="function" name="hb_unicode_compose ()" link="harfbuzz-hb-unicode.html#hb-unicode-compose" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_compose_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-compose-func-t"/>
-    <keyword type="function" name="hb_unicode_decompose ()" link="harfbuzz-hb-unicode.html#hb-unicode-decompose" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_decompose_compatibility ()" link="harfbuzz-hb-unicode.html#hb-unicode-decompose-compatibility" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_decompose_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-decompose-func-t"/>
-    <keyword type="function" name="hb_unicode_eastasian_width ()" link="harfbuzz-hb-unicode.html#hb-unicode-eastasian-width" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_create ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-create" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_destroy ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-destroy" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_get_default ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-default"/>
-    <keyword type="function" name="hb_unicode_funcs_get_empty ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-empty" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_get_parent ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-parent" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_get_user_data ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-user-data" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_is_immutable ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-is-immutable" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_make_immutable ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-make-immutable" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_reference ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-reference" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_combining_class_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-combining-class-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_compose_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-compose-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_decompose_compatibility_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-compatibility-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_decompose_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_eastasian_width_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-eastasian-width-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_general_category_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-general-category-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_mirroring_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-mirroring-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_script_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-script-func" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_funcs_set_user_data ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-user-data" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_general_category ()" link="harfbuzz-hb-unicode.html#hb-unicode-general-category" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_general_category_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-general-category-func-t"/>
-    <keyword type="function" name="hb_unicode_mirroring ()" link="harfbuzz-hb-unicode.html#hb-unicode-mirroring" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_mirroring_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-mirroring-func-t"/>
-    <keyword type="function" name="hb_unicode_script ()" link="harfbuzz-hb-unicode.html#hb-unicode-script" since="0.9.2"/>
-    <keyword type="function" name="hb_unicode_script_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-script-func-t"/>
-    <keyword type="macro" name="HB_UNICODE_MAX_DECOMPOSITION_LEN" link="harfbuzz-hb-unicode.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS"/>
-    <keyword type="enum" name="enum hb_unicode_combining_class_t" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class-t"/>
-    <keyword type="typedef" name="hb_unicode_funcs_t" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"/>
-    <keyword type="enum" name="enum hb_unicode_general_category_t" link="harfbuzz-hb-unicode.html#hb-unicode-general-category-t"/>
-    <keyword type="function" name="hb_buffer_create ()" link="harfbuzz-Buffers.html#hb-buffer-create" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_reference ()" link="harfbuzz-Buffers.html#hb-buffer-reference" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_empty ()" link="harfbuzz-Buffers.html#hb-buffer-get-empty" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_destroy ()" link="harfbuzz-Buffers.html#hb-buffer-destroy" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_reset ()" link="harfbuzz-Buffers.html#hb-buffer-reset" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_clear_contents ()" link="harfbuzz-Buffers.html#hb-buffer-clear-contents" since="0.9.11"/>
-    <keyword type="function" name="hb_buffer_pre_allocate ()" link="harfbuzz-Buffers.html#hb-buffer-pre-allocate" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_allocation_successful ()" link="harfbuzz-Buffers.html#hb-buffer-allocation-successful" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_add ()" link="harfbuzz-Buffers.html#hb-buffer-add" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_add_codepoints ()" link="harfbuzz-Buffers.html#hb-buffer-add-codepoints" since="0.9.31"/>
-    <keyword type="function" name="hb_buffer_add_utf32 ()" link="harfbuzz-Buffers.html#hb-buffer-add-utf32" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_add_utf16 ()" link="harfbuzz-Buffers.html#hb-buffer-add-utf16" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_add_utf8 ()" link="harfbuzz-Buffers.html#hb-buffer-add-utf8" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_add_latin1 ()" link="harfbuzz-Buffers.html#hb-buffer-add-latin1" since="0.9.39"/>
-    <keyword type="function" name="hb_buffer_append ()" link="harfbuzz-Buffers.html#hb-buffer-append" since="1.5.0"/>
-    <keyword type="function" name="hb_buffer_set_content_type ()" link="harfbuzz-Buffers.html#hb-buffer-set-content-type" since="0.9.5"/>
-    <keyword type="function" name="hb_buffer_get_content_type ()" link="harfbuzz-Buffers.html#hb-buffer-get-content-type" since="0.9.5"/>
-    <keyword type="function" name="hb_buffer_set_direction ()" link="harfbuzz-Buffers.html#hb-buffer-set-direction" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_direction ()" link="harfbuzz-Buffers.html#hb-buffer-get-direction" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_script ()" link="harfbuzz-Buffers.html#hb-buffer-set-script" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_script ()" link="harfbuzz-Buffers.html#hb-buffer-get-script" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_language ()" link="harfbuzz-Buffers.html#hb-buffer-set-language" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_language ()" link="harfbuzz-Buffers.html#hb-buffer-get-language" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_flags ()" link="harfbuzz-Buffers.html#hb-buffer-set-flags" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_get_flags ()" link="harfbuzz-Buffers.html#hb-buffer-get-flags" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_set_cluster_level ()" link="harfbuzz-Buffers.html#hb-buffer-set-cluster-level" since="0.9.42"/>
-    <keyword type="function" name="hb_buffer_get_cluster_level ()" link="harfbuzz-Buffers.html#hb-buffer-get-cluster-level" since="0.9.42"/>
-    <keyword type="function" name="hb_buffer_set_length ()" link="harfbuzz-Buffers.html#hb-buffer-set-length" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_length ()" link="harfbuzz-Buffers.html#hb-buffer-get-length" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_segment_properties ()" link="harfbuzz-Buffers.html#hb-buffer-set-segment-properties" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_get_segment_properties ()" link="harfbuzz-Buffers.html#hb-buffer-get-segment-properties" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_guess_segment_properties ()" link="harfbuzz-Buffers.html#hb-buffer-guess-segment-properties" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_set_unicode_funcs ()" link="harfbuzz-Buffers.html#hb-buffer-set-unicode-funcs" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_unicode_funcs ()" link="harfbuzz-Buffers.html#hb-buffer-get-unicode-funcs" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_user_data ()" link="harfbuzz-Buffers.html#hb-buffer-set-user-data" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_user_data ()" link="harfbuzz-Buffers.html#hb-buffer-get-user-data" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_glyph_infos ()" link="harfbuzz-Buffers.html#hb-buffer-get-glyph-infos" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_get_glyph_positions ()" link="harfbuzz-Buffers.html#hb-buffer-get-glyph-positions" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_set_replacement_codepoint ()" link="harfbuzz-Buffers.html#hb-buffer-set-replacement-codepoint" since="0.9.31"/>
-    <keyword type="function" name="hb_buffer_get_replacement_codepoint ()" link="harfbuzz-Buffers.html#hb-buffer-get-replacement-codepoint" since="0.9.31"/>
-    <keyword type="function" name="hb_buffer_normalize_glyphs ()" link="harfbuzz-Buffers.html#hb-buffer-normalize-glyphs" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_reverse ()" link="harfbuzz-Buffers.html#hb-buffer-reverse" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_reverse_range ()" link="harfbuzz-Buffers.html#hb-buffer-reverse-range" since="0.9.41"/>
-    <keyword type="function" name="hb_buffer_reverse_clusters ()" link="harfbuzz-Buffers.html#hb-buffer-reverse-clusters" since="0.9.2"/>
-    <keyword type="function" name="hb_buffer_serialize_glyphs ()" link="harfbuzz-Buffers.html#hb-buffer-serialize-glyphs" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_deserialize_glyphs ()" link="harfbuzz-Buffers.html#hb-buffer-deserialize-glyphs" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_serialize_format_from_string ()" link="harfbuzz-Buffers.html#hb-buffer-serialize-format-from-string" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_serialize_format_to_string ()" link="harfbuzz-Buffers.html#hb-buffer-serialize-format-to-string" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_serialize_list_formats ()" link="harfbuzz-Buffers.html#hb-buffer-serialize-list-formats" since="0.9.7"/>
-    <keyword type="function" name="hb_segment_properties_equal ()" link="harfbuzz-Buffers.html#hb-segment-properties-equal" since="0.9.7"/>
-    <keyword type="function" name="hb_segment_properties_hash ()" link="harfbuzz-Buffers.html#hb-segment-properties-hash" since="0.9.7"/>
-    <keyword type="function" name="hb_buffer_diff ()" link="harfbuzz-Buffers.html#hb-buffer-diff" since="1.5.0"/>
-    <keyword type="function" name="hb_buffer_set_message_func ()" link="harfbuzz-Buffers.html#hb-buffer-set-message-func" since="1.1.3"/>
-    <keyword type="function" name="hb_glyph_info_get_glyph_flags ()" link="harfbuzz-Buffers.html#hb-glyph-info-get-glyph-flags" since="1.5.0"/>
-    <keyword type="function" name="hb_buffer_message_func_t ()" link="harfbuzz-Buffers.html#hb-buffer-message-func-t"/>
-    <keyword type="macro" name="HB_SEGMENT_PROPERTIES_DEFAULT" link="harfbuzz-Buffers.html#HB-SEGMENT-PROPERTIES-DEFAULT:CAPS"/>
-    <keyword type="macro" name="HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT" link="harfbuzz-Buffers.html#HB-BUFFER-REPLACEMENT-CODEPOINT-DEFAULT:CAPS" since="0.9.31"/>
-    <keyword type="typedef" name="hb_buffer_t" link="harfbuzz-Buffers.html#hb-buffer-t"/>
-    <keyword type="struct" name="hb_glyph_info_t" link="harfbuzz-Buffers.html#hb-glyph-info-t-struct"/>
-    <keyword type="enum" name="enum hb_glyph_flags_t" link="harfbuzz-Buffers.html#hb-glyph-flags-t"/>
-    <keyword type="struct" name="hb_glyph_position_t" link="harfbuzz-Buffers.html#hb-glyph-position-t-struct"/>
-    <keyword type="enum" name="enum hb_buffer_content_type_t" link="harfbuzz-Buffers.html#hb-buffer-content-type-t"/>
-    <keyword type="enum" name="enum hb_buffer_flags_t" link="harfbuzz-Buffers.html#hb-buffer-flags-t" since="0.9.20"/>
-    <keyword type="enum" name="enum hb_buffer_cluster_level_t" link="harfbuzz-Buffers.html#hb-buffer-cluster-level-t"/>
-    <keyword type="struct" name="hb_segment_properties_t" link="harfbuzz-Buffers.html#hb-segment-properties-t-struct"/>
-    <keyword type="enum" name="enum hb_buffer_serialize_format_t" link="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" since="0.9.2"/>
-    <keyword type="enum" name="enum hb_buffer_serialize_flags_t" link="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" since="0.9.20"/>
-    <keyword type="enum" name="enum hb_buffer_diff_flags_t" link="harfbuzz-Buffers.html#hb-buffer-diff-flags-t"/>
-    <keyword type="function" name="hb_blob_create ()" link="harfbuzz-hb-blob.html#hb-blob-create" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_create_from_file ()" link="harfbuzz-hb-blob.html#hb-blob-create-from-file" since="1.7.7"/>
-    <keyword type="function" name="hb_blob_create_sub_blob ()" link="harfbuzz-hb-blob.html#hb-blob-create-sub-blob" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_copy_writable_or_fail ()" link="harfbuzz-hb-blob.html#hb-blob-copy-writable-or-fail" since="1.8.0"/>
-    <keyword type="function" name="hb_blob_destroy ()" link="harfbuzz-hb-blob.html#hb-blob-destroy" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_get_data ()" link="harfbuzz-hb-blob.html#hb-blob-get-data" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_get_data_writable ()" link="harfbuzz-hb-blob.html#hb-blob-get-data-writable" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_get_empty ()" link="harfbuzz-hb-blob.html#hb-blob-get-empty" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_get_length ()" link="harfbuzz-hb-blob.html#hb-blob-get-length" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_get_user_data ()" link="harfbuzz-hb-blob.html#hb-blob-get-user-data" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_is_immutable ()" link="harfbuzz-hb-blob.html#hb-blob-is-immutable" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_make_immutable ()" link="harfbuzz-hb-blob.html#hb-blob-make-immutable" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_reference ()" link="harfbuzz-hb-blob.html#hb-blob-reference" since="0.9.2"/>
-    <keyword type="function" name="hb_blob_set_user_data ()" link="harfbuzz-hb-blob.html#hb-blob-set-user-data" since="0.9.2"/>
-    <keyword type="typedef" name="hb_blob_t" link="harfbuzz-hb-blob.html#hb-blob-t"/>
-    <keyword type="enum" name="enum hb_memory_mode_t" link="harfbuzz-hb-blob.html#hb-memory-mode-t"/>
-    <keyword type="function" name="hb_face_count ()" link="harfbuzz-hb-face.html#hb-face-count"/>
+    <keyword type="function" name="hb_font_get_glyph_func_t ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" deprecated=""/>
+    <keyword type="function" name="hb_ot_layout_table_find_script ()" link="harfbuzz-hb-deprecated.html#hb-ot-layout-table-find-script"/>
+    <keyword type="function" name="hb_font_funcs_set_glyph_h_kerning_func ()" link="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-h-kerning-func" deprecated="2.0.0" since="0.9.2"/>
+    <keyword type="function" name="hb_font_funcs_set_glyph_v_kerning_func ()" link="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-v-kerning-func" deprecated="2.0.0" since="0.9.2"/>
+    <keyword type="function" name="hb_font_get_glyph_h_kerning ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning" deprecated="2.0.0" since="0.9.2"/>
+    <keyword type="function" name="hb_font_get_glyph_kerning_for_direction ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-for-direction" deprecated="2.0.0" since="0.9.2"/>
+    <keyword type="function" name="hb_font_get_glyph_kerning_func_t ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-kerning-func-t" deprecated=""/>
+    <keyword type="function" name="hb_font_get_glyph_v_kerning ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning" deprecated="2.0.0" since="0.9.2"/>
+    <keyword type="macro" name="HB_BUFFER_FLAGS_DEFAULT" link="harfbuzz-hb-deprecated.html#HB-BUFFER-FLAGS-DEFAULT:CAPS" deprecated=""/>
+    <keyword type="macro" name="HB_BUFFER_SERIALIZE_FLAGS_DEFAULT" link="harfbuzz-hb-deprecated.html#HB-BUFFER-SERIALIZE-FLAGS-DEFAULT:CAPS" deprecated=""/>
+    <keyword type="macro" name="HB_SCRIPT_CANADIAN_ABORIGINAL" link="harfbuzz-hb-deprecated.html#HB-SCRIPT-CANADIAN-ABORIGINAL:CAPS" deprecated=""/>
+    <keyword type="macro" name="HB_OT_VAR_NO_AXIS_INDEX" link="harfbuzz-hb-deprecated.html#HB-OT-VAR-NO-AXIS-INDEX:CAPS" deprecated="2.2.0" since="1.4.2"/>
+    <keyword type="macro" name="HB_UNICODE_MAX_DECOMPOSITION_LEN" link="harfbuzz-hb-deprecated.html#HB-UNICODE-MAX-DECOMPOSITION-LEN:CAPS" deprecated="2.0.0"/>
+    <keyword type="typedef" name="hb_font_get_glyph_h_kerning_func_t" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-h-kerning-func-t" deprecated=""/>
+    <keyword type="typedef" name="hb_font_get_glyph_v_kerning_func_t" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-v-kerning-func-t" deprecated=""/>
+    <keyword type="function" name="hb_face_count ()" link="harfbuzz-hb-face.html#hb-face-count" since="1.7.7"/>
     <keyword type="function" name="hb_face_create ()" link="harfbuzz-hb-face.html#hb-face-create" since="0.9.2"/>
     <keyword type="function" name="hb_face_create_for_tables ()" link="harfbuzz-hb-face.html#hb-face-create-for-tables" since="0.9.2"/>
     <keyword type="function" name="hb_face_destroy ()" link="harfbuzz-hb-face.html#hb-face-destroy" since="0.9.2"/>
     <keyword type="function" name="hb_face_set_index ()" link="harfbuzz-hb-face.html#hb-face-set-index" since="0.9.2"/>
     <keyword type="function" name="hb_face_set_upem ()" link="harfbuzz-hb-face.html#hb-face-set-upem" since="0.9.2"/>
     <keyword type="function" name="hb_face_set_user_data ()" link="harfbuzz-hb-face.html#hb-face-set-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_face_collect_unicodes ()" link="harfbuzz-hb-face.html#hb-face-collect-unicodes" since="1.9.0"/>
+    <keyword type="function" name="hb_face_collect_variation_selectors ()" link="harfbuzz-hb-face.html#hb-face-collect-variation-selectors" since="1.9.0"/>
+    <keyword type="function" name="hb_face_collect_variation_unicodes ()" link="harfbuzz-hb-face.html#hb-face-collect-variation-unicodes" since="1.9.0"/>
+    <keyword type="function" name="hb_face_builder_create ()" link="harfbuzz-hb-face.html#hb-face-builder-create" since="1.9.0"/>
+    <keyword type="function" name="hb_face_builder_add_table ()" link="harfbuzz-hb-face.html#hb-face-builder-add-table" since="1.9.0"/>
     <keyword type="typedef" name="hb_face_t" link="harfbuzz-hb-face.html#hb-face-t"/>
     <keyword type="function" name="hb_font_add_glyph_origin_for_direction ()" link="harfbuzz-hb-font.html#hb-font-add-glyph-origin-for-direction" since="0.9.2"/>
     <keyword type="function" name="hb_font_create ()" link="harfbuzz-hb-font.html#hb-font-create" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_extents_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-extents-func" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_from_name_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-from-name-func" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_h_advance_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advance-func" since="0.9.2"/>
-    <keyword type="function" name="hb_font_funcs_set_glyph_h_kerning_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-kerning-func" since="0.9.2"/>
+    <keyword type="function" name="hb_font_funcs_set_glyph_h_advances_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-advances-func" since="1.8.6"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_h_origin_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-h-origin-func" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_name_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-name-func" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_v_advance_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advance-func" since="0.9.2"/>
-    <keyword type="function" name="hb_font_funcs_set_glyph_v_kerning_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-kerning-func" since="0.9.2"/>
+    <keyword type="function" name="hb_font_funcs_set_glyph_v_advances_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-advances-func" since="1.8.6"/>
     <keyword type="function" name="hb_font_funcs_set_glyph_v_origin_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-glyph-v-origin-func" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_nominal_glyph_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyph-func" since="1.2.3"/>
+    <keyword type="function" name="hb_font_funcs_set_nominal_glyphs_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-nominal-glyphs-func" since="2.0.0"/>
     <keyword type="function" name="hb_font_funcs_set_user_data ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-user-data" since="0.9.2"/>
     <keyword type="function" name="hb_font_funcs_set_variation_glyph_func ()" link="harfbuzz-hb-font.html#hb-font-funcs-set-variation-glyph-func" since="1.2.3"/>
     <keyword type="function" name="hb_font_get_empty ()" link="harfbuzz-hb-font.html#hb-font-get-empty" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph ()" link="harfbuzz-hb-font.html#hb-font-get-glyph" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_advance_for_direction ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-advance-for-direction" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_advance_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-advance-func-t"/>
+    <keyword type="function" name="hb_font_get_glyph_advances_for_direction ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-advances-for-direction" since="1.8.6"/>
+    <keyword type="function" name="hb_font_get_glyph_advances_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-advances-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_contour_point ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-contour-point" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_contour_point_for_origin ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-contour-point-for-origin" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_contour_point_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-contour-point-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_from_name ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-from-name" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_from_name_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-from-name-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_h_advance ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-advance" since="0.9.2"/>
-    <keyword type="function" name="hb_font_get_glyph_h_kerning ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning" since="0.9.2"/>
+    <keyword type="function" name="hb_font_get_glyph_h_advances ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances" since="1.8.6"/>
     <keyword type="function" name="hb_font_get_glyph_h_origin ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-origin" since="0.9.2"/>
-    <keyword type="function" name="hb_font_get_glyph_kerning_for_direction ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-for-direction" since="0.9.2"/>
-    <keyword type="function" name="hb_font_get_glyph_kerning_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-kerning-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_name ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-name" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_name_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-name-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_origin_for_direction ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-origin-for-direction" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_glyph_origin_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-origin-func-t"/>
     <keyword type="function" name="hb_font_get_glyph_v_advance ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-advance" since="0.9.2"/>
-    <keyword type="function" name="hb_font_get_glyph_v_kerning ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning" since="0.9.2"/>
+    <keyword type="function" name="hb_font_get_glyph_v_advances ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances" since="1.8.6"/>
     <keyword type="function" name="hb_font_get_glyph_v_origin ()" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-origin" since="0.9.2"/>
     <keyword type="function" name="hb_font_get_nominal_glyph ()" link="harfbuzz-hb-font.html#hb-font-get-nominal-glyph" since="1.2.3"/>
     <keyword type="function" name="hb_font_get_nominal_glyph_func_t ()" link="harfbuzz-hb-font.html#hb-font-get-nominal-glyph-func-t"/>
     <keyword type="function" name="hb_font_get_v_extents ()" link="harfbuzz-hb-font.html#hb-font-get-v-extents" since="1.1.3"/>
     <keyword type="typedef" name="hb_font_funcs_t" link="harfbuzz-hb-font.html#hb-font-funcs-t"/>
     <keyword type="typedef" name="hb_font_get_glyph_h_advance_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-advance-func-t"/>
-    <keyword type="typedef" name="hb_font_get_glyph_h_kerning_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-kerning-func-t"/>
+    <keyword type="typedef" name="hb_font_get_glyph_h_advances_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-advances-func-t"/>
     <keyword type="typedef" name="hb_font_get_glyph_h_origin_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-h-origin-func-t"/>
     <keyword type="typedef" name="hb_font_get_glyph_v_advance_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-advance-func-t"/>
-    <keyword type="typedef" name="hb_font_get_glyph_v_kerning_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-kerning-func-t"/>
+    <keyword type="typedef" name="hb_font_get_glyph_v_advances_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-advances-func-t"/>
     <keyword type="typedef" name="hb_font_get_glyph_v_origin_func_t" link="harfbuzz-hb-font.html#hb-font-get-glyph-v-origin-func-t"/>
     <keyword type="struct" name="hb_variation_t" link="harfbuzz-hb-font.html#hb-variation-t" since="1.4.2"/>
     <keyword type="typedef" name="hb_font_t" link="harfbuzz-hb-font.html#hb-font-t"/>
     <keyword type="typedef" name="hb_font_get_font_h_extents_func_t" link="harfbuzz-hb-font.html#hb-font-get-font-h-extents-func-t"/>
     <keyword type="typedef" name="hb_font_get_font_v_extents_func_t" link="harfbuzz-hb-font.html#hb-font-get-font-v-extents-func-t"/>
-    <keyword type="function" name="hb_feature_from_string ()" link="harfbuzz-Shaping.html#hb-feature-from-string" since="0.9.5"/>
-    <keyword type="function" name="hb_feature_to_string ()" link="harfbuzz-Shaping.html#hb-feature-to-string" since="0.9.5"/>
-    <keyword type="function" name="hb_shape ()" link="harfbuzz-Shaping.html#hb-shape" since="0.9.2"/>
-    <keyword type="function" name="hb_shape_full ()" link="harfbuzz-Shaping.html#hb-shape-full" since="0.9.2"/>
-    <keyword type="function" name="hb_shape_list_shapers ()" link="harfbuzz-Shaping.html#hb-shape-list-shapers" since="0.9.2"/>
-    <keyword type="struct" name="hb_feature_t" link="harfbuzz-Shaping.html#hb-feature-t-struct"/>
-    <keyword type="macro" name="HB_VERSION_ATLEAST()" link="harfbuzz-hb-version.html#HB-VERSION-ATLEAST:CAPS"/>
-    <keyword type="function" name="hb_version ()" link="harfbuzz-hb-version.html#hb-version" since="0.9.2"/>
-    <keyword type="function" name="hb_version_atleast ()" link="harfbuzz-hb-version.html#hb-version-atleast" since="0.9.30"/>
-    <keyword type="function" name="hb_version_string ()" link="harfbuzz-hb-version.html#hb-version-string" since="0.9.2"/>
-    <keyword type="macro" name="HB_VERSION_MAJOR" link="harfbuzz-hb-version.html#HB-VERSION-MAJOR:CAPS"/>
-    <keyword type="macro" name="HB_VERSION_MICRO" link="harfbuzz-hb-version.html#HB-VERSION-MICRO:CAPS"/>
-    <keyword type="macro" name="HB_VERSION_MINOR" link="harfbuzz-hb-version.html#HB-VERSION-MINOR:CAPS"/>
-    <keyword type="macro" name="HB_VERSION_STRING" link="harfbuzz-hb-version.html#HB-VERSION-STRING:CAPS"/>
-    <keyword type="function" name="hb_font_funcs_set_glyph_func ()" link="harfbuzz-hb-deprecated.html#hb-font-funcs-set-glyph-func" deprecated="1.2.3" since="0.9.2"/>
-    <keyword type="function" name="hb_font_get_glyph_func_t ()" link="harfbuzz-hb-deprecated.html#hb-font-get-glyph-func-t" deprecated=""/>
-    <keyword type="function" name="hb_set_invert ()" link="harfbuzz-hb-deprecated.html#hb-set-invert" deprecated="1.6.1" since="0.9.10"/>
-    <keyword type="macro" name="HB_BUFFER_FLAGS_DEFAULT" link="harfbuzz-hb-deprecated.html#HB-BUFFER-FLAGS-DEFAULT:CAPS" deprecated=""/>
-    <keyword type="macro" name="HB_BUFFER_SERIALIZE_FLAGS_DEFAULT" link="harfbuzz-hb-deprecated.html#HB-BUFFER-SERIALIZE-FLAGS-DEFAULT:CAPS" deprecated=""/>
-    <keyword type="macro" name="HB_SCRIPT_CANADIAN_ABORIGINAL" link="harfbuzz-hb-deprecated.html#HB-SCRIPT-CANADIAN-ABORIGINAL:CAPS" deprecated=""/>
+    <keyword type="function" name="hb_map_allocation_successful ()" link="harfbuzz-hb-map.html#hb-map-allocation-successful" since="1.7.7"/>
+    <keyword type="function" name="hb_map_clear ()" link="harfbuzz-hb-map.html#hb-map-clear" since="1.7.7"/>
+    <keyword type="function" name="hb_map_create ()" link="harfbuzz-hb-map.html#hb-map-create" since="1.7.7"/>
+    <keyword type="function" name="hb_map_del ()" link="harfbuzz-hb-map.html#hb-map-del" since="1.7.7"/>
+    <keyword type="function" name="hb_map_destroy ()" link="harfbuzz-hb-map.html#hb-map-destroy" since="1.7.7"/>
+    <keyword type="function" name="hb_map_get ()" link="harfbuzz-hb-map.html#hb-map-get" since="1.7.7"/>
+    <keyword type="function" name="hb_map_get_empty ()" link="harfbuzz-hb-map.html#hb-map-get-empty" since="1.7.7"/>
+    <keyword type="function" name="hb_map_get_population ()" link="harfbuzz-hb-map.html#hb-map-get-population" since="1.7.7"/>
+    <keyword type="function" name="hb_map_get_user_data ()" link="harfbuzz-hb-map.html#hb-map-get-user-data" since="1.7.7"/>
+    <keyword type="function" name="hb_map_has ()" link="harfbuzz-hb-map.html#hb-map-has" since="1.7.7"/>
+    <keyword type="function" name="hb_map_is_empty ()" link="harfbuzz-hb-map.html#hb-map-is-empty" since="1.7.7"/>
+    <keyword type="function" name="hb_map_reference ()" link="harfbuzz-hb-map.html#hb-map-reference" since="1.7.7"/>
+    <keyword type="function" name="hb_map_set ()" link="harfbuzz-hb-map.html#hb-map-set" since="1.7.7"/>
+    <keyword type="function" name="hb_map_set_user_data ()" link="harfbuzz-hb-map.html#hb-map-set-user-data" since="1.7.7"/>
+    <keyword type="macro" name="HB_MAP_VALUE_INVALID" link="harfbuzz-hb-map.html#HB-MAP-VALUE-INVALID:CAPS"/>
+    <keyword type="typedef" name="hb_map_t" link="harfbuzz-hb-map.html#hb-map-t"/>
     <keyword type="function" name="hb_set_add ()" link="harfbuzz-hb-set.html#hb-set-add" since="0.9.2"/>
     <keyword type="function" name="hb_set_add_range ()" link="harfbuzz-hb-set.html#hb-set-add-range" since="0.9.7"/>
     <keyword type="function" name="hb_set_allocation_successful ()" link="harfbuzz-hb-set.html#hb-set-allocation-successful" since="0.9.2"/>
     <keyword type="function" name="hb_set_union ()" link="harfbuzz-hb-set.html#hb-set-union" since="0.9.2"/>
     <keyword type="macro" name="HB_SET_VALUE_INVALID" link="harfbuzz-hb-set.html#HB-SET-VALUE-INVALID:CAPS"/>
     <keyword type="typedef" name="hb_set_t" link="harfbuzz-hb-set.html#hb-set-t"/>
+    <keyword type="function" name="hb_shape_plan_create ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_create_cached ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create-cached" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_create2 ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create2"/>
+    <keyword type="function" name="hb_shape_plan_create_cached2 ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create-cached2"/>
+    <keyword type="function" name="hb_shape_plan_destroy ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-destroy" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_execute ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-execute" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_get_empty ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-empty" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_get_shaper ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-shaper" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_get_user_data ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-user-data" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_reference ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-reference" since="0.9.7"/>
+    <keyword type="function" name="hb_shape_plan_set_user_data ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-set-user-data" since="0.9.7"/>
+    <keyword type="typedef" name="hb_shape_plan_t" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"/>
+    <keyword type="function" name="hb_feature_from_string ()" link="harfbuzz-hb-shape.html#hb-feature-from-string" since="0.9.5"/>
+    <keyword type="function" name="hb_feature_to_string ()" link="harfbuzz-hb-shape.html#hb-feature-to-string" since="0.9.5"/>
+    <keyword type="function" name="hb_shape ()" link="harfbuzz-hb-shape.html#hb-shape" since="0.9.2"/>
+    <keyword type="function" name="hb_shape_full ()" link="harfbuzz-hb-shape.html#hb-shape-full" since="0.9.2"/>
+    <keyword type="function" name="hb_shape_list_shapers ()" link="harfbuzz-hb-shape.html#hb-shape-list-shapers" since="0.9.2"/>
+    <keyword type="macro" name="HB_FEATURE_GLOBAL_END" link="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-END:CAPS" since="2.0.0"/>
+    <keyword type="macro" name="HB_FEATURE_GLOBAL_START" link="harfbuzz-hb-shape.html#HB-FEATURE-GLOBAL-START:CAPS" since="2.0.0"/>
+    <keyword type="struct" name="hb_feature_t" link="harfbuzz-hb-shape.html#hb-feature-t-struct"/>
+    <keyword type="function" name="hb_unicode_combining_class ()" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_combining_class_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class-func-t"/>
+    <keyword type="function" name="hb_unicode_compose ()" link="harfbuzz-hb-unicode.html#hb-unicode-compose" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_compose_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-compose-func-t"/>
+    <keyword type="function" name="hb_unicode_decompose ()" link="harfbuzz-hb-unicode.html#hb-unicode-decompose" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_decompose_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-decompose-func-t"/>
+    <keyword type="function" name="hb_unicode_funcs_create ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-create" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_destroy ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-destroy" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_get_default ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-default"/>
+    <keyword type="function" name="hb_unicode_funcs_get_empty ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-empty" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_get_parent ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-parent" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_get_user_data ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-get-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_is_immutable ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-is-immutable" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_make_immutable ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-make-immutable" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_reference ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-reference" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_combining_class_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-combining-class-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_compose_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-compose-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_decompose_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-decompose-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_general_category_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-general-category-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_mirroring_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-mirroring-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_script_func ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-script-func" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_funcs_set_user_data ()" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-set-user-data" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_general_category ()" link="harfbuzz-hb-unicode.html#hb-unicode-general-category" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_general_category_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-general-category-func-t"/>
+    <keyword type="function" name="hb_unicode_mirroring ()" link="harfbuzz-hb-unicode.html#hb-unicode-mirroring" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_mirroring_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-mirroring-func-t"/>
+    <keyword type="function" name="hb_unicode_script ()" link="harfbuzz-hb-unicode.html#hb-unicode-script" since="0.9.2"/>
+    <keyword type="function" name="hb_unicode_script_func_t ()" link="harfbuzz-hb-unicode.html#hb-unicode-script-func-t"/>
+    <keyword type="macro" name="HB_UNICODE_MAX" link="harfbuzz-hb-unicode.html#HB-UNICODE-MAX:CAPS" since="1.9.0"/>
+    <keyword type="enum" name="enum hb_unicode_combining_class_t" link="harfbuzz-hb-unicode.html#hb-unicode-combining-class-t"/>
+    <keyword type="typedef" name="hb_unicode_funcs_t" link="harfbuzz-hb-unicode.html#hb-unicode-funcs-t"/>
+    <keyword type="enum" name="enum hb_unicode_general_category_t" link="harfbuzz-hb-unicode.html#hb-unicode-general-category-t"/>
+    <keyword type="macro" name="HB_VERSION_ATLEAST()" link="harfbuzz-hb-version.html#HB-VERSION-ATLEAST:CAPS"/>
+    <keyword type="function" name="hb_version ()" link="harfbuzz-hb-version.html#hb-version" since="0.9.2"/>
+    <keyword type="function" name="hb_version_atleast ()" link="harfbuzz-hb-version.html#hb-version-atleast" since="0.9.30"/>
+    <keyword type="function" name="hb_version_string ()" link="harfbuzz-hb-version.html#hb-version-string" since="0.9.2"/>
+    <keyword type="macro" name="HB_VERSION_MAJOR" link="harfbuzz-hb-version.html#HB-VERSION-MAJOR:CAPS"/>
+    <keyword type="macro" name="HB_VERSION_MICRO" link="harfbuzz-hb-version.html#HB-VERSION-MICRO:CAPS"/>
+    <keyword type="macro" name="HB_VERSION_MINOR" link="harfbuzz-hb-version.html#HB-VERSION-MINOR:CAPS"/>
+    <keyword type="macro" name="HB_VERSION_STRING" link="harfbuzz-hb-version.html#HB-VERSION-STRING:CAPS"/>
+    <keyword type="macro" name="HB_COLOR()" link="harfbuzz-hb-ot-color.html#HB-COLOR:CAPS"/>
+    <keyword type="macro" name="hb_color_get_alpha()" link="harfbuzz-hb-ot-color.html#hb-color-get-alpha" since="2.1.0"/>
+    <keyword type="macro" name="hb_color_get_blue()" link="harfbuzz-hb-ot-color.html#hb-color-get-blue" since="2.1.0"/>
+    <keyword type="macro" name="hb_color_get_green()" link="harfbuzz-hb-ot-color.html#hb-color-get-green" since="2.1.0"/>
+    <keyword type="macro" name="hb_color_get_red()" link="harfbuzz-hb-ot-color.html#hb-color-get-red" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_glyph_get_layers ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-get-layers" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_glyph_reference_png ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-png" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_glyph_reference_svg ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-glyph-reference-svg" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_has_layers ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-has-layers" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_has_palettes ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-has-palettes" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_has_png ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-has-png" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_has_svg ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-has-svg" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_palette_color_get_name_id ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-color-get-name-id" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_palette_get_colors ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-colors" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_palette_get_count ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-count" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_palette_get_flags ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-flags" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_color_palette_get_name_id ()" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-get-name-id" since="2.1.0"/>
+    <keyword type="typedef" name="hb_color_t" link="harfbuzz-hb-ot-color.html#hb-color-t" since="2.1.0"/>
+    <keyword type="enum" name="enum hb_ot_color_palette_flags_t" link="harfbuzz-hb-ot-color.html#hb-ot-color-palette-flags-t" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_font_set_funcs ()" link="harfbuzz-hb-ot-font.html#hb-ot-font-set-funcs" since="0.9.28"/>
+    <keyword type="function" name="hb_ot_tag_to_language ()" link="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-language" since="0.9.2"/>
+    <keyword type="function" name="hb_ot_tag_to_script ()" link="harfbuzz-hb-ot-layout.html#hb-ot-tag-to-script"/>
+    <keyword type="function" name="hb_ot_tags_from_script_and_language ()" link="harfbuzz-hb-ot-layout.html#hb-ot-tags-from-script-and-language" since="2.0.0"/>
+    <keyword type="function" name="hb_ot_tags_to_script_and_language ()" link="harfbuzz-hb-ot-layout.html#hb-ot-tags-to-script-and-language" since="2.0.0"/>
     <keyword type="function" name="hb_ot_layout_collect_lookups ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-lookups" since="0.9.8"/>
+    <keyword type="function" name="hb_ot_layout_collect_features ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-collect-features" since="1.8.5"/>
+    <keyword type="function" name="hb_ot_layout_feature_get_characters ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-characters" since="2.0.0"/>
     <keyword type="function" name="hb_ot_layout_feature_get_lookups ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-lookups" since="0.9.7"/>
+    <keyword type="function" name="hb_ot_layout_feature_get_name_ids ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-get-name-ids" since="2.0.0"/>
     <keyword type="function" name="hb_ot_layout_feature_with_variations_get_lookups ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-feature-with-variations-get-lookups"/>
     <keyword type="function" name="hb_ot_layout_get_attach_points ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-get-attach-points"/>
     <keyword type="function" name="hb_ot_layout_get_glyph_class ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-get-glyph-class" since="0.9.7"/>
     <keyword type="function" name="hb_ot_layout_lookup_substitute_closure ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-lookup-substitute-closure" since="0.9.7"/>
     <keyword type="function" name="hb_ot_layout_lookups_substitute_closure ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-lookups-substitute-closure" since="1.8.1"/>
     <keyword type="function" name="hb_ot_layout_lookup_would_substitute ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-lookup-would-substitute" since="0.9.7"/>
-    <keyword type="function" name="hb_ot_layout_script_find_language ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-find-language"/>
     <keyword type="function" name="hb_ot_layout_script_get_language_tags ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-get-language-tags"/>
-    <keyword type="function" name="hb_ot_layout_table_choose_script ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-choose-script"/>
+    <keyword type="function" name="hb_ot_layout_script_select_language ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-script-select-language" since="2.0.0"/>
     <keyword type="function" name="hb_ot_layout_table_find_feature_variations ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-find-feature-variations"/>
-    <keyword type="function" name="hb_ot_layout_table_find_script ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-find-script"/>
     <keyword type="function" name="hb_ot_layout_table_get_feature_tags ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-feature-tags"/>
     <keyword type="function" name="hb_ot_layout_table_get_script_tags ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-script-tags"/>
     <keyword type="function" name="hb_ot_layout_table_get_lookup_count ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-get-lookup-count" since="0.9.22"/>
+    <keyword type="function" name="hb_ot_layout_table_select_script ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-table-select-script" since="2.0.0"/>
     <keyword type="function" name="hb_ot_shape_plan_collect_lookups ()" link="harfbuzz-hb-ot-layout.html#hb-ot-shape-plan-collect-lookups" since="0.9.7"/>
     <keyword type="function" name="hb_ot_layout_language_get_required_feature_index ()" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-language-get-required-feature-index"/>
+    <keyword type="macro" name="HB_OT_MAX_TAGS_PER_LANGUAGE" link="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-LANGUAGE:CAPS" since="2.0.0"/>
+    <keyword type="macro" name="HB_OT_MAX_TAGS_PER_SCRIPT" link="harfbuzz-hb-ot-layout.html#HB-OT-MAX-TAGS-PER-SCRIPT:CAPS" since="2.0.0"/>
+    <keyword type="macro" name="HB_OT_TAG_DEFAULT_LANGUAGE" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_DEFAULT_SCRIPT" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS"/>
     <keyword type="macro" name="HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-DEFAULT-LANGUAGE-INDEX:CAPS"/>
     <keyword type="macro" name="HB_OT_LAYOUT_NO_FEATURE_INDEX" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-NO-FEATURE-INDEX:CAPS"/>
     <keyword type="macro" name="HB_OT_LAYOUT_NO_SCRIPT_INDEX" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-NO-SCRIPT-INDEX:CAPS"/>
     <keyword type="macro" name="HB_OT_LAYOUT_NO_VARIATIONS_INDEX" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-NO-VARIATIONS-INDEX:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_BASE" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-BASE:CAPS"/>
     <keyword type="macro" name="HB_OT_TAG_GDEF" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-GDEF:CAPS"/>
     <keyword type="macro" name="HB_OT_TAG_GPOS" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-GPOS:CAPS"/>
     <keyword type="macro" name="HB_OT_TAG_GSUB" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-GSUB:CAPS"/>
     <keyword type="macro" name="HB_OT_TAG_JSTF" link="harfbuzz-hb-ot-layout.html#HB-OT-TAG-JSTF:CAPS"/>
     <keyword type="enum" name="enum hb_ot_layout_glyph_class_t" link="harfbuzz-hb-ot-layout.html#hb-ot-layout-glyph-class-t"/>
-    <keyword type="function" name="hb_ot_tag_from_language ()" link="harfbuzz-hb-ot-tag.html#hb-ot-tag-from-language"/>
-    <keyword type="function" name="hb_ot_tag_to_language ()" link="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-language" since="0.9.2"/>
-    <keyword type="function" name="hb_ot_tag_to_script ()" link="harfbuzz-hb-ot-tag.html#hb-ot-tag-to-script"/>
-    <keyword type="function" name="hb_ot_tags_from_script ()" link="harfbuzz-hb-ot-tag.html#hb-ot-tags-from-script"/>
-    <keyword type="macro" name="HB_OT_TAG_DEFAULT_LANGUAGE" link="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-LANGUAGE:CAPS"/>
-    <keyword type="macro" name="HB_OT_TAG_DEFAULT_SCRIPT" link="harfbuzz-hb-ot-tag.html#HB-OT-TAG-DEFAULT-SCRIPT:CAPS"/>
-    <keyword type="function" name="hb_ot_font_set_funcs ()" link="harfbuzz-hb-ot-font.html#hb-ot-font-set-funcs" since="0.9.28"/>
-    <keyword type="function" name="hb_ot_shape_glyphs_closure ()" link="harfbuzz-hb-ot-shape.html#hb-ot-shape-glyphs-closure" since="0.9.2"/>
     <keyword type="function" name="hb_ot_math_has_data ()" link="harfbuzz-hb-ot-math.html#hb-ot-math-has-data" since="1.3.3"/>
     <keyword type="function" name="hb_ot_math_get_constant ()" link="harfbuzz-hb-ot-math.html#hb-ot-math-get-constant" since="1.3.3"/>
     <keyword type="function" name="hb_ot_math_get_glyph_italics_correction ()" link="harfbuzz-hb-ot-math.html#hb-ot-math-get-glyph-italics-correction" since="1.3.3"/>
     <keyword type="struct" name="hb_ot_math_glyph_variant_t" link="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-variant-t-struct"/>
     <keyword type="enum" name="enum hb_ot_math_glyph_part_flags_t" link="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-part-flags-t" since="1.3.3"/>
     <keyword type="struct" name="hb_ot_math_glyph_part_t" link="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-part-t-struct"/>
-    <keyword type="function" name="hb_shape_plan_create ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_create_cached ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create-cached" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_create2 ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create2"/>
-    <keyword type="function" name="hb_shape_plan_create_cached2 ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-create-cached2"/>
-    <keyword type="function" name="hb_shape_plan_destroy ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-destroy" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_execute ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-execute" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_get_empty ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-empty" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_get_shaper ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-shaper" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_get_user_data ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-get-user-data" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_reference ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-reference" since="0.9.7"/>
-    <keyword type="function" name="hb_shape_plan_set_user_data ()" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-set-user-data" since="0.9.7"/>
-    <keyword type="typedef" name="hb_shape_plan_t" link="harfbuzz-hb-shape-plan.html#hb-shape-plan-t"/>
-    <keyword type="function" name="hb_glib_get_unicode_funcs ()" link="harfbuzz-hb-glib.html#hb-glib-get-unicode-funcs"/>
-    <keyword type="function" name="hb_glib_script_from_script ()" link="harfbuzz-hb-glib.html#hb-glib-script-from-script"/>
-    <keyword type="function" name="hb_glib_script_to_script ()" link="harfbuzz-hb-glib.html#hb-glib-script-to-script"/>
-    <keyword type="function" name="hb_glib_blob_create ()" link="harfbuzz-hb-glib.html#hb-glib-blob-create" since="0.9.38"/>
-    <keyword type="function" name="hb_icu_get_unicode_funcs ()" link="harfbuzz-hb-icu.html#hb-icu-get-unicode-funcs"/>
-    <keyword type="function" name="hb_icu_script_from_script ()" link="harfbuzz-hb-icu.html#hb-icu-script-from-script"/>
-    <keyword type="function" name="hb_icu_script_to_script ()" link="harfbuzz-hb-icu.html#hb-icu-script-to-script"/>
+    <keyword type="function" name="hb_ot_name_list_names ()" link="harfbuzz-hb-ot-name.html#hb-ot-name-list-names" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_name_get_utf16 ()" link="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf16" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_name_get_utf32 ()" link="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf32" since="2.1.0"/>
+    <keyword type="function" name="hb_ot_name_get_utf8 ()" link="harfbuzz-hb-ot-name.html#hb-ot-name-get-utf8" since="2.1.0"/>
+    <keyword type="typedef" name="hb_ot_name_id_t" link="harfbuzz-hb-ot-name.html#hb-ot-name-id-t" since="2.0.0"/>
+    <keyword type="function" name="hb_ot_shape_glyphs_closure ()" link="harfbuzz-hb-ot-shape.html#hb-ot-shape-glyphs-closure" since="0.9.2"/>
+    <keyword type="function" name="hb_ot_var_has_data ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-has-data" since="1.4.2"/>
+    <keyword type="function" name="hb_ot_var_find_axis_info ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-find-axis-info" since="2.2.0"/>
+    <keyword type="function" name="hb_ot_var_get_axis_count ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-count" since="1.4.2"/>
+    <keyword type="function" name="hb_ot_var_get_axis_infos ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-infos" since="2.2.0"/>
+    <keyword type="function" name="hb_ot_var_get_named_instance_count ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-get-named-instance-count"/>
+    <keyword type="function" name="hb_ot_var_named_instance_get_subfamily_name_id ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-subfamily-name-id"/>
+    <keyword type="function" name="hb_ot_var_named_instance_get_postscript_name_id ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-postscript-name-id"/>
+    <keyword type="function" name="hb_ot_var_named_instance_get_design_coords ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-named-instance-get-design-coords"/>
+    <keyword type="function" name="hb_ot_var_normalize_variations ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-variations" since="1.4.2"/>
+    <keyword type="function" name="hb_ot_var_normalize_coords ()" link="harfbuzz-hb-ot-var.html#hb-ot-var-normalize-coords" since="1.4.2"/>
+    <keyword type="macro" name="HB_OT_TAG_VAR_AXIS_ITALIC" link="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-ITALIC:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE" link="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-OPTICAL-SIZE:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_VAR_AXIS_SLANT" link="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-SLANT:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_VAR_AXIS_WEIGHT" link="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WEIGHT:CAPS"/>
+    <keyword type="macro" name="HB_OT_TAG_VAR_AXIS_WIDTH" link="harfbuzz-hb-ot-var.html#HB-OT-TAG-VAR-AXIS-WIDTH:CAPS"/>
+    <keyword type="enum" name="enum hb_ot_var_axis_flags_t" link="harfbuzz-hb-ot-var.html#hb-ot-var-axis-flags-t" since="2.2.0"/>
+    <keyword type="function" name="hb_aat_layout_feature_type_get_name_id ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-name-id" since="2.2.0"/>
+    <keyword type="function" name="hb_aat_layout_feature_type_get_selector_infos ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-get-selector-infos"/>
+    <keyword type="function" name="hb_aat_layout_get_feature_types ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-get-feature-types" since="2.2.0"/>
+    <keyword type="function" name="hb_aat_layout_has_positioning ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-positioning"/>
+    <keyword type="function" name="hb_aat_layout_has_substitution ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-substitution"/>
+    <keyword type="function" name="hb_aat_layout_has_tracking ()" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-has-tracking"/>
+    <keyword type="macro" name="HB_AAT_LAYOUT_NO_SELECTOR_INDEX" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-NO-SELECTOR-INDEX:CAPS"/>
+    <keyword type="enum" name="enum hb_aat_layout_feature_type_t" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-type-t" since="2.2.0"/>
+    <keyword type="enum" name="enum hb_aat_layout_feature_selector_t" link="harfbuzz-hb-aat-layout.html#hb-aat-layout-feature-selector-t" since="2.2.0"/>
+    <keyword type="function" name="hb_coretext_face_create ()" link="harfbuzz-hb-coretext.html#hb-coretext-face-create"/>
+    <keyword type="function" name="hb_coretext_font_create ()" link="harfbuzz-hb-coretext.html#hb-coretext-font-create"/>
+    <keyword type="function" name="hb_coretext_face_get_cg_font ()" link="harfbuzz-hb-coretext.html#hb-coretext-face-get-cg-font"/>
+    <keyword type="function" name="hb_coretext_font_get_ct_font ()" link="harfbuzz-hb-coretext.html#hb-coretext-font-get-ct-font"/>
+    <keyword type="macro" name="HB_CORETEXT_TAG_KERX" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-KERX:CAPS"/>
+    <keyword type="macro" name="HB_CORETEXT_TAG_MORT" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-MORT:CAPS"/>
+    <keyword type="macro" name="HB_CORETEXT_TAG_MORX" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-MORX:CAPS"/>
     <keyword type="function" name="hb_ft_face_create ()" link="harfbuzz-hb-ft.html#hb-ft-face-create" since="0.9.2"/>
     <keyword type="function" name="hb_ft_face_create_cached ()" link="harfbuzz-hb-ft.html#hb-ft-face-create-cached" since="0.9.2"/>
     <keyword type="function" name="hb_ft_face_create_referenced ()" link="harfbuzz-hb-ft.html#hb-ft-face-create-referenced" since="0.9.38"/>
     <keyword type="function" name="hb_ft_font_set_load_flags ()" link="harfbuzz-hb-ft.html#hb-ft-font-set-load-flags" since="1.0.5"/>
     <keyword type="function" name="hb_ft_font_get_load_flags ()" link="harfbuzz-hb-ft.html#hb-ft-font-get-load-flags" since="1.0.5"/>
     <keyword type="function" name="hb_ft_font_set_funcs ()" link="harfbuzz-hb-ft.html#hb-ft-font-set-funcs"/>
-    <keyword type="function" name="hb_graphite2_face_get_gr_face ()" link="harfbuzz-hb-graphite2.html#hb-graphite2-face-get-gr-face"/>
-    <keyword type="function" name="hb_graphite2_font_get_gr_font ()" link="harfbuzz-hb-graphite2.html#hb-graphite2-font-get-gr-font" deprecated=""/>
-    <keyword type="macro" name="HB_GRAPHITE2_TAG_SILF" link="harfbuzz-hb-graphite2.html#HB-GRAPHITE2-TAG-SILF:CAPS"/>
-    <keyword type="function" name="hb_uniscribe_font_get_hfont ()" link="harfbuzz-hb-uniscribe.html#hb-uniscribe-font-get-hfont"/>
-    <keyword type="function" name="hb_uniscribe_font_get_logfontw ()" link="harfbuzz-hb-uniscribe.html#hb-uniscribe-font-get-logfontw"/>
-    <keyword type="function" name="hb_coretext_face_create ()" link="harfbuzz-hb-coretext.html#hb-coretext-face-create"/>
-    <keyword type="function" name="hb_coretext_font_create ()" link="harfbuzz-hb-coretext.html#hb-coretext-font-create"/>
-    <keyword type="function" name="hb_coretext_face_get_cg_font ()" link="harfbuzz-hb-coretext.html#hb-coretext-face-get-cg-font"/>
-    <keyword type="function" name="hb_coretext_font_get_ct_font ()" link="harfbuzz-hb-coretext.html#hb-coretext-font-get-ct-font"/>
-    <keyword type="macro" name="HB_CORETEXT_TAG_KERX" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-KERX:CAPS"/>
-    <keyword type="macro" name="HB_CORETEXT_TAG_MORT" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-MORT:CAPS"/>
-    <keyword type="macro" name="HB_CORETEXT_TAG_MORX" link="harfbuzz-hb-coretext.html#HB-CORETEXT-TAG-MORX:CAPS"/>
+    <keyword type="function" name="hb_glib_get_unicode_funcs ()" link="harfbuzz-hb-glib.html#hb-glib-get-unicode-funcs"/>
+    <keyword type="function" name="hb_glib_script_from_script ()" link="harfbuzz-hb-glib.html#hb-glib-script-from-script"/>
+    <keyword type="function" name="hb_glib_script_to_script ()" link="harfbuzz-hb-glib.html#hb-glib-script-to-script"/>
+    <keyword type="function" name="hb_glib_blob_create ()" link="harfbuzz-hb-glib.html#hb-glib-blob-create" since="0.9.38"/>
     <keyword type="function" name="hb_gobject_blob_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-blob-get-type" since="0.9.2"/>
     <keyword type="function" name="hb_gobject_buffer_content_type_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-buffer-content-type-get-type"/>
     <keyword type="function" name="hb_gobject_buffer_diff_flags_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-buffer-diff-flags-get-type"/>
     <keyword type="function" name="hb_gobject_font_funcs_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-font-funcs-get-type" since="0.9.2"/>
     <keyword type="function" name="hb_gobject_font_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-font-get-type" since="0.9.2"/>
     <keyword type="function" name="hb_gobject_glyph_flags_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-glyph-flags-get-type"/>
+    <keyword type="function" name="hb_gobject_map_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-map-get-type"/>
     <keyword type="function" name="hb_gobject_memory_mode_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-memory-mode-get-type"/>
+    <keyword type="function" name="hb_gobject_ot_color_palette_flags_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-ot-color-palette-flags-get-type"/>
     <keyword type="function" name="hb_gobject_ot_layout_glyph_class_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-ot-layout-glyph-class-get-type"/>
     <keyword type="function" name="hb_gobject_ot_math_constant_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-ot-math-constant-get-type"/>
     <keyword type="function" name="hb_gobject_ot_math_glyph_part_get_type ()" link="harfbuzz-hb-gobject.html#hb-gobject-ot-math-glyph-part-get-type"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_FONT" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-FONT:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_FONT_FUNCS" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-FONT-FUNCS:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_GLYPH_FLAGS" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-GLYPH-FLAGS:CAPS"/>
+    <keyword type="macro" name="HB_GOBJECT_TYPE_MAP" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MAP:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_MEMORY_MODE" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-MEMORY-MODE:CAPS"/>
+    <keyword type="macro" name="HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-COLOR-PALETTE-FLAGS:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-LAYOUT-GLYPH-CLASS:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_OT_MATH_CONSTANT" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-MATH-CONSTANT:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-OT-MATH-GLYPH-PART:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_SEGMENT_PROPERTIES" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-SEGMENT-PROPERTIES:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_SET" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-SET:CAPS"/>
     <keyword type="macro" name="HB_GOBJECT_TYPE_USER_DATA_KEY" link="harfbuzz-hb-gobject.html#HB-GOBJECT-TYPE-USER-DATA-KEY:CAPS"/>
+    <keyword type="function" name="hb_graphite2_face_get_gr_face ()" link="harfbuzz-hb-graphite2.html#hb-graphite2-face-get-gr-face"/>
+    <keyword type="macro" name="HB_GRAPHITE2_TAG_SILF" link="harfbuzz-hb-graphite2.html#HB-GRAPHITE2-TAG-SILF:CAPS"/>
+    <keyword type="function" name="hb_icu_get_unicode_funcs ()" link="harfbuzz-hb-icu.html#hb-icu-get-unicode-funcs"/>
+    <keyword type="function" name="hb_icu_script_from_script ()" link="harfbuzz-hb-icu.html#hb-icu-script-from-script"/>
+    <keyword type="function" name="hb_icu_script_to_script ()" link="harfbuzz-hb-icu.html#hb-icu-script-to-script"/>
+    <keyword type="function" name="hb_uniscribe_font_get_hfont ()" link="harfbuzz-hb-uniscribe.html#hb-uniscribe-font-get-hfont"/>
+    <keyword type="function" name="hb_uniscribe_font_get_logfontw ()" link="harfbuzz-hb-uniscribe.html#hb-uniscribe-font-get-logfontw"/>
+    <keyword type="constant" name="HB_MEMORY_MODE_DUPLICATE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-DUPLICATE:CAPS"/>
+    <keyword type="constant" name="HB_MEMORY_MODE_READONLY" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-READONLY:CAPS"/>
+    <keyword type="constant" name="HB_MEMORY_MODE_WRITABLE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-WRITABLE:CAPS"/>
+    <keyword type="constant" name="HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-READONLY-MAY-MAKE-WRITABLE:CAPS"/>
+    <keyword type="constant" name="HB_GLYPH_FLAG_UNSAFE_TO_BREAK" link="harfbuzz-hb-buffer.html#HB-GLYPH-FLAG-UNSAFE-TO-BREAK:CAPS"/>
+    <keyword type="constant" name="HB_GLYPH_FLAG_DEFINED" link="harfbuzz-hb-buffer.html#HB-GLYPH-FLAG-DEFINED:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_INVALID" link="harfbuzz-hb-buffer.html#HB-BUFFER-CONTENT-TYPE-INVALID:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_UNICODE" link="harfbuzz-hb-buffer.html#HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_GLYPHS" link="harfbuzz-hb-buffer.html#HB-BUFFER-CONTENT-TYPE-GLYPHS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_FLAG_DEFAULT" link="harfbuzz-hb-buffer.html#HB-BUFFER-FLAG-DEFAULT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_FLAG_BOT" link="harfbuzz-hb-buffer.html#HB-BUFFER-FLAG-BOT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_FLAG_EOT" link="harfbuzz-hb-buffer.html#HB-BUFFER-FLAG-EOT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES" link="harfbuzz-hb-buffer.html#HB-BUFFER-FLAG-PRESERVE-DEFAULT-IGNORABLES:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES" link="harfbuzz-hb-buffer.html#HB-BUFFER-FLAG-REMOVE-DEFAULT-IGNORABLES:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES" link="harfbuzz-hb-buffer.html#HB-BUFFER-CLUSTER-LEVEL-MONOTONE-GRAPHEMES:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS" link="harfbuzz-hb-buffer.html#HB-BUFFER-CLUSTER-LEVEL-MONOTONE-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_CHARACTERS" link="harfbuzz-hb-buffer.html#HB-BUFFER-CLUSTER-LEVEL-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_DEFAULT" link="harfbuzz-hb-buffer.html#HB-BUFFER-CLUSTER-LEVEL-DEFAULT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_TEXT" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FORMAT-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_JSON" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FORMAT-JSON:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_INVALID" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FORMAT-INVALID:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_DEFAULT" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-DEFAULT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-FLAGS:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES" link="harfbuzz-hb-buffer.html#HB-BUFFER-SERIALIZE-FLAG-NO-ADVANCES:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_EQUAL" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-EQUAL:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-CONTENT-TYPE-MISMATCH:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-LENGTH-MISMATCH:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-CODEPOINT-MISMATCH:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-CLUSTER-MISMATCH:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-GLYPH-FLAGS-MISMATCH:CAPS"/>
+    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH" link="harfbuzz-hb-buffer.html#HB-BUFFER-DIFF-FLAG-POSITION-MISMATCH:CAPS"/>
     <keyword type="constant" name="HB_DIRECTION_INVALID" link="harfbuzz-hb-common.html#HB-DIRECTION-INVALID:CAPS"/>
     <keyword type="constant" name="HB_DIRECTION_LTR" link="harfbuzz-hb-common.html#HB-DIRECTION-LTR:CAPS"/>
     <keyword type="constant" name="HB_DIRECTION_RTL" link="harfbuzz-hb-common.html#HB-DIRECTION-RTL:CAPS"/>
     <keyword type="constant" name="HB_DIRECTION_TTB" link="harfbuzz-hb-common.html#HB-DIRECTION-TTB:CAPS"/>
     <keyword type="constant" name="HB_DIRECTION_BTT" link="harfbuzz-hb-common.html#HB-DIRECTION-BTT:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_COMMON" link="harfbuzz-hb-common.html#HB-SCRIPT-COMMON:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_INHERITED" link="harfbuzz-hb-common.html#HB-SCRIPT-INHERITED:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_UNKNOWN" link="harfbuzz-hb-common.html#HB-SCRIPT-UNKNOWN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ARABIC" link="harfbuzz-hb-common.html#HB-SCRIPT-ARABIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ARMENIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-ARMENIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BENGALI" link="harfbuzz-hb-common.html#HB-SCRIPT-BENGALI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CYRILLIC" link="harfbuzz-hb-common.html#HB-SCRIPT-CYRILLIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_DEVANAGARI" link="harfbuzz-hb-common.html#HB-SCRIPT-DEVANAGARI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GEORGIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-GEORGIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GREEK" link="harfbuzz-hb-common.html#HB-SCRIPT-GREEK:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GUJARATI" link="harfbuzz-hb-common.html#HB-SCRIPT-GUJARATI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GURMUKHI" link="harfbuzz-hb-common.html#HB-SCRIPT-GURMUKHI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HANGUL" link="harfbuzz-hb-common.html#HB-SCRIPT-HANGUL:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HAN" link="harfbuzz-hb-common.html#HB-SCRIPT-HAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HEBREW" link="harfbuzz-hb-common.html#HB-SCRIPT-HEBREW:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HIRAGANA" link="harfbuzz-hb-common.html#HB-SCRIPT-HIRAGANA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KANNADA" link="harfbuzz-hb-common.html#HB-SCRIPT-KANNADA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KATAKANA" link="harfbuzz-hb-common.html#HB-SCRIPT-KATAKANA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LAO" link="harfbuzz-hb-common.html#HB-SCRIPT-LAO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LATIN" link="harfbuzz-hb-common.html#HB-SCRIPT-LATIN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MALAYALAM" link="harfbuzz-hb-common.html#HB-SCRIPT-MALAYALAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ORIYA" link="harfbuzz-hb-common.html#HB-SCRIPT-ORIYA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAMIL" link="harfbuzz-hb-common.html#HB-SCRIPT-TAMIL:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TELUGU" link="harfbuzz-hb-common.html#HB-SCRIPT-TELUGU:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_THAI" link="harfbuzz-hb-common.html#HB-SCRIPT-THAI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TIBETAN" link="harfbuzz-hb-common.html#HB-SCRIPT-TIBETAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BOPOMOFO" link="harfbuzz-hb-common.html#HB-SCRIPT-BOPOMOFO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BRAILLE" link="harfbuzz-hb-common.html#HB-SCRIPT-BRAILLE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CANADIAN_SYLLABICS" link="harfbuzz-hb-common.html#HB-SCRIPT-CANADIAN-SYLLABICS:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CHEROKEE" link="harfbuzz-hb-common.html#HB-SCRIPT-CHEROKEE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ETHIOPIC" link="harfbuzz-hb-common.html#HB-SCRIPT-ETHIOPIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KHMER" link="harfbuzz-hb-common.html#HB-SCRIPT-KHMER:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MONGOLIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-MONGOLIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MYANMAR" link="harfbuzz-hb-common.html#HB-SCRIPT-MYANMAR:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OGHAM" link="harfbuzz-hb-common.html#HB-SCRIPT-OGHAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_RUNIC" link="harfbuzz-hb-common.html#HB-SCRIPT-RUNIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SINHALA" link="harfbuzz-hb-common.html#HB-SCRIPT-SINHALA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SYRIAC" link="harfbuzz-hb-common.html#HB-SCRIPT-SYRIAC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_THAANA" link="harfbuzz-hb-common.html#HB-SCRIPT-THAANA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_YI" link="harfbuzz-hb-common.html#HB-SCRIPT-YI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_DESERET" link="harfbuzz-hb-common.html#HB-SCRIPT-DESERET:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GOTHIC" link="harfbuzz-hb-common.html#HB-SCRIPT-GOTHIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_ITALIC" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-ITALIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BUHID" link="harfbuzz-hb-common.html#HB-SCRIPT-BUHID:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HANUNOO" link="harfbuzz-hb-common.html#HB-SCRIPT-HANUNOO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAGALOG" link="harfbuzz-hb-common.html#HB-SCRIPT-TAGALOG:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAGBANWA" link="harfbuzz-hb-common.html#HB-SCRIPT-TAGBANWA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CYPRIOT" link="harfbuzz-hb-common.html#HB-SCRIPT-CYPRIOT:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LIMBU" link="harfbuzz-hb-common.html#HB-SCRIPT-LIMBU:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LINEAR_B" link="harfbuzz-hb-common.html#HB-SCRIPT-LINEAR-B:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OSMANYA" link="harfbuzz-hb-common.html#HB-SCRIPT-OSMANYA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SHAVIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-SHAVIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAI_LE" link="harfbuzz-hb-common.html#HB-SCRIPT-TAI-LE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_UGARITIC" link="harfbuzz-hb-common.html#HB-SCRIPT-UGARITIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BUGINESE" link="harfbuzz-hb-common.html#HB-SCRIPT-BUGINESE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_COPTIC" link="harfbuzz-hb-common.html#HB-SCRIPT-COPTIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GLAGOLITIC" link="harfbuzz-hb-common.html#HB-SCRIPT-GLAGOLITIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KHAROSHTHI" link="harfbuzz-hb-common.html#HB-SCRIPT-KHAROSHTHI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_NEW_TAI_LUE" link="harfbuzz-hb-common.html#HB-SCRIPT-NEW-TAI-LUE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_PERSIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-PERSIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SYLOTI_NAGRI" link="harfbuzz-hb-common.html#HB-SCRIPT-SYLOTI-NAGRI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TIFINAGH" link="harfbuzz-hb-common.html#HB-SCRIPT-TIFINAGH:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BALINESE" link="harfbuzz-hb-common.html#HB-SCRIPT-BALINESE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CUNEIFORM" link="harfbuzz-hb-common.html#HB-SCRIPT-CUNEIFORM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_NKO" link="harfbuzz-hb-common.html#HB-SCRIPT-NKO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PHAGS_PA" link="harfbuzz-hb-common.html#HB-SCRIPT-PHAGS-PA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PHOENICIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-PHOENICIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CARIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-CARIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CHAM" link="harfbuzz-hb-common.html#HB-SCRIPT-CHAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KAYAH_LI" link="harfbuzz-hb-common.html#HB-SCRIPT-KAYAH-LI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LEPCHA" link="harfbuzz-hb-common.html#HB-SCRIPT-LEPCHA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LYCIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-LYCIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LYDIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-LYDIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OL_CHIKI" link="harfbuzz-hb-common.html#HB-SCRIPT-OL-CHIKI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_REJANG" link="harfbuzz-hb-common.html#HB-SCRIPT-REJANG:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SAURASHTRA" link="harfbuzz-hb-common.html#HB-SCRIPT-SAURASHTRA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SUNDANESE" link="harfbuzz-hb-common.html#HB-SCRIPT-SUNDANESE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_VAI" link="harfbuzz-hb-common.html#HB-SCRIPT-VAI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_AVESTAN" link="harfbuzz-hb-common.html#HB-SCRIPT-AVESTAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BAMUM" link="harfbuzz-hb-common.html#HB-SCRIPT-BAMUM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_EGYPTIAN_HIEROGLYPHS" link="harfbuzz-hb-common.html#HB-SCRIPT-EGYPTIAN-HIEROGLYPHS:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_IMPERIAL_ARAMAIC" link="harfbuzz-hb-common.html#HB-SCRIPT-IMPERIAL-ARAMAIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_INSCRIPTIONAL_PAHLAVI" link="harfbuzz-hb-common.html#HB-SCRIPT-INSCRIPTIONAL-PAHLAVI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_INSCRIPTIONAL_PARTHIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-INSCRIPTIONAL-PARTHIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_JAVANESE" link="harfbuzz-hb-common.html#HB-SCRIPT-JAVANESE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KAITHI" link="harfbuzz-hb-common.html#HB-SCRIPT-KAITHI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LISU" link="harfbuzz-hb-common.html#HB-SCRIPT-LISU:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MEETEI_MAYEK" link="harfbuzz-hb-common.html#HB-SCRIPT-MEETEI-MAYEK:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_SOUTH_ARABIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-SOUTH-ARABIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_TURKIC" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-TURKIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SAMARITAN" link="harfbuzz-hb-common.html#HB-SCRIPT-SAMARITAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAI_THAM" link="harfbuzz-hb-common.html#HB-SCRIPT-TAI-THAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAI_VIET" link="harfbuzz-hb-common.html#HB-SCRIPT-TAI-VIET:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BATAK" link="harfbuzz-hb-common.html#HB-SCRIPT-BATAK:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BRAHMI" link="harfbuzz-hb-common.html#HB-SCRIPT-BRAHMI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MANDAIC" link="harfbuzz-hb-common.html#HB-SCRIPT-MANDAIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CHAKMA" link="harfbuzz-hb-common.html#HB-SCRIPT-CHAKMA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MEROITIC_CURSIVE" link="harfbuzz-hb-common.html#HB-SCRIPT-MEROITIC-CURSIVE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MEROITIC_HIEROGLYPHS" link="harfbuzz-hb-common.html#HB-SCRIPT-MEROITIC-HIEROGLYPHS:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MIAO" link="harfbuzz-hb-common.html#HB-SCRIPT-MIAO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SHARADA" link="harfbuzz-hb-common.html#HB-SCRIPT-SHARADA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SORA_SOMPENG" link="harfbuzz-hb-common.html#HB-SCRIPT-SORA-SOMPENG:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TAKRI" link="harfbuzz-hb-common.html#HB-SCRIPT-TAKRI:CAPS"/>
     <keyword type="constant" name="HB_SCRIPT_BASSA_VAH" link="harfbuzz-hb-common.html#HB-SCRIPT-BASSA-VAH:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_CAUCASIAN_ALBANIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-CAUCASIAN-ALBANIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_DUPLOYAN" link="harfbuzz-hb-common.html#HB-SCRIPT-DUPLOYAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ELBASAN" link="harfbuzz-hb-common.html#HB-SCRIPT-ELBASAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GRANTHA" link="harfbuzz-hb-common.html#HB-SCRIPT-GRANTHA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KHOJKI" link="harfbuzz-hb-common.html#HB-SCRIPT-KHOJKI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_KHUDAWADI" link="harfbuzz-hb-common.html#HB-SCRIPT-KHUDAWADI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_LINEAR_A" link="harfbuzz-hb-common.html#HB-SCRIPT-LINEAR-A:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MAHAJANI" link="harfbuzz-hb-common.html#HB-SCRIPT-MAHAJANI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MANICHAEAN" link="harfbuzz-hb-common.html#HB-SCRIPT-MANICHAEAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MENDE_KIKAKUI" link="harfbuzz-hb-common.html#HB-SCRIPT-MENDE-KIKAKUI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MODI" link="harfbuzz-hb-common.html#HB-SCRIPT-MODI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MRO" link="harfbuzz-hb-common.html#HB-SCRIPT-MRO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_NABATAEAN" link="harfbuzz-hb-common.html#HB-SCRIPT-NABATAEAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_NORTH_ARABIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-NORTH-ARABIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_PERMIC" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-PERMIC:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PAHAWH_HMONG" link="harfbuzz-hb-common.html#HB-SCRIPT-PAHAWH-HMONG:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PALMYRENE" link="harfbuzz-hb-common.html#HB-SCRIPT-PALMYRENE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PAU_CIN_HAU" link="harfbuzz-hb-common.html#HB-SCRIPT-PAU-CIN-HAU:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_PSALTER_PAHLAVI" link="harfbuzz-hb-common.html#HB-SCRIPT-PSALTER-PAHLAVI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SIDDHAM" link="harfbuzz-hb-common.html#HB-SCRIPT-SIDDHAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TIRHUTA" link="harfbuzz-hb-common.html#HB-SCRIPT-TIRHUTA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_WARANG_CITI" link="harfbuzz-hb-common.html#HB-SCRIPT-WARANG-CITI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_AHOM" link="harfbuzz-hb-common.html#HB-SCRIPT-AHOM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ANATOLIAN_HIEROGLYPHS" link="harfbuzz-hb-common.html#HB-SCRIPT-ANATOLIAN-HIEROGLYPHS:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HATRAN" link="harfbuzz-hb-common.html#HB-SCRIPT-HATRAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MULTANI" link="harfbuzz-hb-common.html#HB-SCRIPT-MULTANI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_HUNGARIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-HUNGARIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SIGNWRITING" link="harfbuzz-hb-common.html#HB-SCRIPT-SIGNWRITING:CAPS"/>
     <keyword type="constant" name="HB_SCRIPT_ADLAM" link="harfbuzz-hb-common.html#HB-SCRIPT-ADLAM:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_BHAIKSUKI" link="harfbuzz-hb-common.html#HB-SCRIPT-BHAIKSUKI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MARCHEN" link="harfbuzz-hb-common.html#HB-SCRIPT-MARCHEN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OSAGE" link="harfbuzz-hb-common.html#HB-SCRIPT-OSAGE:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_TANGUT" link="harfbuzz-hb-common.html#HB-SCRIPT-TANGUT:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_NEWA" link="harfbuzz-hb-common.html#HB-SCRIPT-NEWA:CAPS"/>
     <keyword type="constant" name="HB_SCRIPT_MASARAM_GONDI" link="harfbuzz-hb-common.html#HB-SCRIPT-MASARAM-GONDI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_NUSHU" link="harfbuzz-hb-common.html#HB-SCRIPT-NUSHU:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SOYOMBO" link="harfbuzz-hb-common.html#HB-SCRIPT-SOYOMBO:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_ZANABAZAR_SQUARE" link="harfbuzz-hb-common.html#HB-SCRIPT-ZANABAZAR-SQUARE:CAPS"/>
     <keyword type="constant" name="HB_SCRIPT_DOGRA" link="harfbuzz-hb-common.html#HB-SCRIPT-DOGRA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_GUNJALA_GONDI" link="harfbuzz-hb-common.html#HB-SCRIPT-GUNJALA-GONDI:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_HANIFI_ROHINGYA" link="harfbuzz-hb-common.html#HB-SCRIPT-HANIFI-ROHINGYA:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MAKASAR" link="harfbuzz-hb-common.html#HB-SCRIPT-MAKASAR:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_MEDEFAIDRIN" link="harfbuzz-hb-common.html#HB-SCRIPT-MEDEFAIDRIN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_OLD_SOGDIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-OLD-SOGDIAN:CAPS"/>
+    <keyword type="constant" name="HB_SCRIPT_SOGDIAN" link="harfbuzz-hb-common.html#HB-SCRIPT-SOGDIAN:CAPS"/>
     <keyword type="constant" name="HB_SCRIPT_INVALID" link="harfbuzz-hb-common.html#HB-SCRIPT-INVALID:CAPS"/>
     <keyword type="constant" name="_HB_SCRIPT_MAX_VALUE" link="harfbuzz-hb-common.html#HB-SCRIPT-MAX-VALUE:CAPS"/>
     <keyword type="constant" name="_HB_SCRIPT_MAX_VALUE_SIGNED" link="harfbuzz-hb-common.html#HB-SCRIPT-MAX-VALUE-SIGNED:CAPS"/>
     <keyword type="constant" name="HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR" link="harfbuzz-hb-unicode.html#HB-UNICODE-GENERAL-CATEGORY-LINE-SEPARATOR:CAPS"/>
     <keyword type="constant" name="HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR" link="harfbuzz-hb-unicode.html#HB-UNICODE-GENERAL-CATEGORY-PARAGRAPH-SEPARATOR:CAPS"/>
     <keyword type="constant" name="HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR" link="harfbuzz-hb-unicode.html#HB-UNICODE-GENERAL-CATEGORY-SPACE-SEPARATOR:CAPS"/>
-    <keyword type="constant" name="HB_GLYPH_FLAG_UNSAFE_TO_BREAK" link="harfbuzz-Buffers.html#HB-GLYPH-FLAG-UNSAFE-TO-BREAK:CAPS"/>
-    <keyword type="constant" name="HB_GLYPH_FLAG_DEFINED" link="harfbuzz-Buffers.html#HB-GLYPH-FLAG-DEFINED:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_INVALID" link="harfbuzz-Buffers.html#HB-BUFFER-CONTENT-TYPE-INVALID:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_UNICODE" link="harfbuzz-Buffers.html#HB-BUFFER-CONTENT-TYPE-UNICODE:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CONTENT_TYPE_GLYPHS" link="harfbuzz-Buffers.html#HB-BUFFER-CONTENT-TYPE-GLYPHS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_FLAG_DEFAULT" link="harfbuzz-Buffers.html#HB-BUFFER-FLAG-DEFAULT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_FLAG_BOT" link="harfbuzz-Buffers.html#HB-BUFFER-FLAG-BOT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_FLAG_EOT" link="harfbuzz-Buffers.html#HB-BUFFER-FLAG-EOT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES" link="harfbuzz-Buffers.html#HB-BUFFER-FLAG-PRESERVE-DEFAULT-IGNORABLES:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES" link="harfbuzz-Buffers.html#HB-BUFFER-FLAG-REMOVE-DEFAULT-IGNORABLES:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES" link="harfbuzz-Buffers.html#HB-BUFFER-CLUSTER-LEVEL-MONOTONE-GRAPHEMES:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS" link="harfbuzz-Buffers.html#HB-BUFFER-CLUSTER-LEVEL-MONOTONE-CHARACTERS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_CHARACTERS" link="harfbuzz-Buffers.html#HB-BUFFER-CLUSTER-LEVEL-CHARACTERS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_CLUSTER_LEVEL_DEFAULT" link="harfbuzz-Buffers.html#HB-BUFFER-CLUSTER-LEVEL-DEFAULT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_TEXT" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FORMAT-TEXT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_JSON" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FORMAT-JSON:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FORMAT_INVALID" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FORMAT-INVALID:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_DEFAULT" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-DEFAULT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-CLUSTERS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-POSITIONS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-GLYPH-NAMES:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-EXTENTS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-GLYPH-FLAGS:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES" link="harfbuzz-Buffers.html#HB-BUFFER-SERIALIZE-FLAG-NO-ADVANCES:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_EQUAL" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-EQUAL:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-CONTENT-TYPE-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-LENGTH-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-NOTDEF-PRESENT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-DOTTED-CIRCLE-PRESENT:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-CODEPOINT-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-CLUSTER-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-GLYPH-FLAGS-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH" link="harfbuzz-Buffers.html#HB-BUFFER-DIFF-FLAG-POSITION-MISMATCH:CAPS"/>
-    <keyword type="constant" name="HB_MEMORY_MODE_DUPLICATE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-DUPLICATE:CAPS"/>
-    <keyword type="constant" name="HB_MEMORY_MODE_READONLY" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-READONLY:CAPS"/>
-    <keyword type="constant" name="HB_MEMORY_MODE_WRITABLE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-WRITABLE:CAPS"/>
-    <keyword type="constant" name="HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE" link="harfbuzz-hb-blob.html#HB-MEMORY-MODE-READONLY-MAY-MAKE-WRITABLE:CAPS"/>
+    <keyword type="constant" name="HB_OT_COLOR_PALETTE_FLAG_DEFAULT" link="harfbuzz-hb-ot-color.html#HB-OT-COLOR-PALETTE-FLAG-DEFAULT:CAPS"/>
+    <keyword type="constant" name="HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND" link="harfbuzz-hb-ot-color.html#HB-OT-COLOR-PALETTE-FLAG-USABLE-WITH-LIGHT-BACKGROUND:CAPS"/>
+    <keyword type="constant" name="HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND" link="harfbuzz-hb-ot-color.html#HB-OT-COLOR-PALETTE-FLAG-USABLE-WITH-DARK-BACKGROUND:CAPS"/>
     <keyword type="constant" name="HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-GLYPH-CLASS-UNCLASSIFIED:CAPS"/>
     <keyword type="constant" name="HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-GLYPH-CLASS-BASE-GLYPH:CAPS"/>
     <keyword type="constant" name="HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE" link="harfbuzz-hb-ot-layout.html#HB-OT-LAYOUT-GLYPH-CLASS-LIGATURE:CAPS"/>
     <keyword type="constant" name="HB_OT_MATH_KERN_BOTTOM_RIGHT" link="harfbuzz-hb-ot-math.html#HB-OT-MATH-KERN-BOTTOM-RIGHT:CAPS"/>
     <keyword type="constant" name="HB_OT_MATH_KERN_BOTTOM_LEFT" link="harfbuzz-hb-ot-math.html#HB-OT-MATH-KERN-BOTTOM-LEFT:CAPS"/>
     <keyword type="constant" name="HB_MATH_GLYPH_PART_FLAG_EXTENDER" link="harfbuzz-hb-ot-math.html#HB-MATH-GLYPH-PART-FLAG-EXTENDER:CAPS"/>
-    <keyword type="member" name="hb-glyph-info-t-struct.codepoint" link="harfbuzz-Buffers.html#hb-glyph-info-t-struct.codepoint"/>
-    <keyword type="member" name="hb-glyph-info-t-struct.mask" link="harfbuzz-Buffers.html#hb-glyph-info-t-struct.mask"/>
-    <keyword type="member" name="hb-glyph-info-t-struct.cluster" link="harfbuzz-Buffers.html#hb-glyph-info-t-struct.cluster"/>
-    <keyword type="member" name="hb-glyph-position-t-struct.x-advance" link="harfbuzz-Buffers.html#hb-glyph-position-t-struct.x-advance"/>
-    <keyword type="member" name="hb-glyph-position-t-struct.y-advance" link="harfbuzz-Buffers.html#hb-glyph-position-t-struct.y-advance"/>
-    <keyword type="member" name="hb-glyph-position-t-struct.x-offset" link="harfbuzz-Buffers.html#hb-glyph-position-t-struct.x-offset"/>
-    <keyword type="member" name="hb-glyph-position-t-struct.y-offset" link="harfbuzz-Buffers.html#hb-glyph-position-t-struct.y-offset"/>
-    <keyword type="member" name="hb-segment-properties-t-struct.direction" link="harfbuzz-Buffers.html#hb-segment-properties-t-struct.direction"/>
-    <keyword type="member" name="hb-segment-properties-t-struct.script" link="harfbuzz-Buffers.html#hb-segment-properties-t-struct.script"/>
-    <keyword type="member" name="hb-segment-properties-t-struct.language" link="harfbuzz-Buffers.html#hb-segment-properties-t-struct.language"/>
+    <keyword type="constant" name="HB_OT_VAR_AXIS_FLAG_HIDDEN" link="harfbuzz-hb-ot-var.html#HB-OT-VAR-AXIS-FLAG-HIDDEN:CAPS"/>
+    <keyword type="constant" name="_HB_OT_VAR_AXIS_FLAG_MAX_VALUE" link="harfbuzz-hb-ot-var.html#HB-OT-VAR-AXIS-FLAG-MAX-VALUE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_INVALID" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-INVALID:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-ALL-TYPOGRAPHIC:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-LIGATURES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CURISVE-CONNECTION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-LETTER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-VERTICAL-SUBSTITUTION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-LINGUISTIC-REARRANGEMENT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-NUMBER-SPACING:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-SMART-SWASH-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-DIACRITICS-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-VERTICAL-POSITION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-FRACTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-OVERLAPPING-CHARACTERS-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-TYPOGRAPHIC-EXTRAS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-MATHEMATICAL-EXTRAS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-ORNAMENT-SETS-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CHARACTER-ALTERNATIVES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-DESIGN-COMPLEXITY-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-STYLE-OPTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CHARACTER-SHAPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-NUMBER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-TEXT-SPACING:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-TRANSLITERATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-ANNOTATION-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-KANA-SPACING-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-IDEOGRAPHIC-SPACING-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-UNICODE-DECOMPOSITION-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-RUBY-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CJK-SYMBOL-ALTERNATIVES-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-IDEOGRAPHIC-ALTERNATIVES-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CJK-VERTICAL-ROMAN-PLACEMENT-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-ITALIC-CJK-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CASE-SENSITIVE-LAYOUT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-ALTERNATE-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-STYLISTIC-ALTERNATIVES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CONTEXTUAL-ALTERNATIVES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-LOWER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-UPPER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-LANGUAGE-TAG-TYPE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-CJK-ROMAN-SPACING-TYPE:CAPS"/>
+    <keyword type="constant" name="_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-TYPE-MAX-VALUE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INVALID:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-TYPE-FEATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-TYPE-FEATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-REQUIRED-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-REQUIRED-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-COMMON-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-COMMON-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-RARE-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-RARE-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LOGOS-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LOGOS-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-REBUS-PICTURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-REBUS-PICTURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DIPHTHONG-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DIPHTHONG-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SQUARED-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SQUARED-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ABBREV-SQUARED-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ABBREV-SQUARED-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SYMBOL-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SYMBOL-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HISTORICAL-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HISTORICAL-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-UNCONNECTED:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PARTIALLY-CONNECTED:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CURSIVE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-AND-LOWER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALL-LOWER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SMALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INITIAL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INITIAL-CAPS-AND-SMALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SUBSTITUTE-VERTICAL-FORMS-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SUBSTITUTE-VERTICAL-FORMS-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINGUISTIC-REARRANGEMENT-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINGUISTIC-REARRANGEMENT-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MONOSPACED-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-THIRD-WIDTH-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-QUARTER-WIDTH-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-INITIAL-SWASHES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-INITIAL-SWASHES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-FINAL-SWASHES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-WORD-FINAL-SWASHES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-INITIAL-SWASHES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-INITIAL-SWASHES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-FINAL-SWASHES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LINE-FINAL-SWASHES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NON-FINAL-SWASHES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NON-FINAL-SWASHES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SHOW-DIACRITICS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HIDE-DIACRITICS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DECOMPOSE-DIACRITICS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NORMAL-POSITION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SUPERIORS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INFERIORS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ORDINALS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SCIENTIFIC-INFERIORS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-FRACTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-VERTICAL-FRACTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DIAGONAL-FRACTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PREVENT-OVERLAP-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PREVENT-OVERLAP-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHENS-TO-EM-DASH-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHENS-TO-EM-DASH-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-EN-DASH-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-EN-DASH-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASHED-ZERO-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASHED-ZERO-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FORM-INTERROBANG-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FORM-INTERROBANG-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SMART-QUOTES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SMART-QUOTES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIODS-TO-ELLIPSIS-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIODS-TO-ELLIPSIS-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-MINUS-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HYPHEN-TO-MINUS-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ASTERISK-TO-MULTIPLY-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ASTERISK-TO-MULTIPLY-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASH-TO-DIVIDE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SLASH-TO-DIVIDE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INEQUALITY-LIGATURES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INEQUALITY-LIGATURES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPONENTS-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPONENTS-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MATHEMATICAL-GREEK-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MATHEMATICAL-GREEK-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ORNAMENTS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DINGBATS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PI-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FLEURONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DECORATIVE-BORDERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INTERNATIONAL-SYMBOLS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MATH-SYMBOLS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ALTERNATES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL1:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL2:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL3:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL4:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DESIGN-LEVEL5:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-STYLE-OPTIONS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DISPLAY-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ENGRAVED-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ILLUMINATED-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TITLING-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SIMPLIFIED-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1978-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1983-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS1990-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-ONE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-TWO:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-THREE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-FOUR:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-ALT-FIVE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-EXPERT-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-JIS2004-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HOJO-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NLCCHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRADITIONAL-NAMES-CHARACTERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-NUMBERS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MONOSPACED-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-THIRD-WIDTH-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-QUARTER-WIDTH-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALT-PROPORTIONAL-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALT-HALF-WIDTH-TEXT:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-TRANSLITERATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HIRAGANA-TO-KATAKANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-KATAKANA-TO-HIRAGANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-KANA-TO-ROMANIZATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMANIZATION-TO-HIRAGANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMANIZATION-TO-KATAKANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-ONE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-TWO:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HANJA-TO-HANGUL-ALT-THREE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-BOX-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ROUNDED-BOX-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CIRCLE-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-CIRCLE-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PARENTHESIS-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PERIOD-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ROMAN-NUMERAL-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DIAMOND-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-BOX-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-INVERTED-ROUNDED-BOX-ANNOTATION:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-IDEOGRAPHS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-IDEOGRAPHS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-IDEOGRAPHS:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CANONICAL-COMPOSITION-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CANONICAL-COMPOSITION-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-COMPATIBILITY-COMPOSITION-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-COMPATIBILITY-COMPOSITION-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRANSCODING-COMPOSITION-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-TRANSCODING-COMPOSITION-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-RUBY-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-RUBY-KANA-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-CJK-SYMBOL-ALTERNATIVES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-ONE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-TWO:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-THREE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-FOUR:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-SYMBOL-ALT-FIVE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-IDEOGRAPHIC-ALTERNATIVES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-ONE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-TWO:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-THREE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-FOUR:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-IDEOGRAPHIC-ALT-FIVE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-VERTICAL-ROMAN-CENTERED:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-VERTICAL-ROMAN-HBASELINE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-CJK-ITALIC-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CJK-ITALIC-ROMAN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-LAYOUT-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-LAYOUT-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-SPACING-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CASE-SENSITIVE-SPACING-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-HORIZ-KANA-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-HORIZ-KANA-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-VERT-KANA-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-ALTERNATE-VERT-KANA-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-NO-STYLISTIC-ALTERNATES:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ONE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ONE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWO-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWO-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THREE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THREE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOUR-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOUR-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIVE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIVE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIX-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIX-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHT-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHT-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ELEVEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-ELEVEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWELVE-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWELVE-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THIRTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-THIRTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOURTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FOURTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIFTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-FIFTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIXTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SIXTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVENTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-SEVENTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHTEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-EIGHTEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINETEEN-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-NINETEEN-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWENTY-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-STYLISTIC-ALT-TWENTY-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-ALTERNATES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-ALTERNATES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SWASH-ALTERNATES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-SWASH-ALTERNATES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-SWASH-ALTERNATES-ON:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-CONTEXTUAL-SWASH-ALTERNATES-OFF:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-LOWER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-SMALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-LOWER-CASE-PETITE-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-UPPER-CASE:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-SMALL-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-UPPER-CASE-PETITE-CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-HALF-WIDTH-CJK-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-PROPORTIONAL-CJK-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-DEFAULT-CJK-ROMAN:CAPS"/>
+    <keyword type="constant" name="HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-FULL-WIDTH-CJK-ROMAN:CAPS"/>
+    <keyword type="constant" name="_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE" link="harfbuzz-hb-aat-layout.html#HB-AAT-LAYOUT-FEATURE-SELECTOR-MAX-VALUE:CAPS"/>
+    <keyword type="member" name="hb-glyph-position-t-struct.x-advance" link="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct.x-advance"/>
+    <keyword type="member" name="hb-glyph-position-t-struct.y-advance" link="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct.y-advance"/>
+    <keyword type="member" name="hb-glyph-position-t-struct.x-offset" link="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct.x-offset"/>
+    <keyword type="member" name="hb-glyph-position-t-struct.y-offset" link="harfbuzz-hb-buffer.html#hb-glyph-position-t-struct.y-offset"/>
+    <keyword type="member" name="hb-segment-properties-t-struct.direction" link="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct.direction"/>
+    <keyword type="member" name="hb-segment-properties-t-struct.script" link="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct.script"/>
+    <keyword type="member" name="hb-segment-properties-t-struct.language" link="harfbuzz-hb-buffer.html#hb-segment-properties-t-struct.language"/>
   </functions>
 </book>
diff --git a/docs/html/hello-harfbuzz.html b/docs/html/hello-harfbuzz.html
deleted file mode 100644 (file)
index edc8985..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Hello, HarfBuzz: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="pt01.html" title="Part I. User's manual">
-<link rel="prev" href="building.html" title="Building">
-<link rel="next" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts"></td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="building.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="buffers-language-script-and-direction.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="chapter">
-<div class="titlepage"><div><div><h2 class="title">
-<a name="hello-harfbuzz"></a>Hello, HarfBuzz</h2></div></div></div>
-<div class="toc"><dl class="toc"><dt><span class="section"><a href="hello-harfbuzz.html#what-harfbuzz-doesnt-do">What HarfBuzz doesn't do</a></span></dt></dl></div>
-<p>
-    Here's the simplest HarfBuzz that can possibly work. We will improve
-    it later.
-  </p>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>
-        Create a buffer and put your text in it.
-      </p></li></ol></div>
-<pre class="programlisting">
-  #include &lt;hb.h&gt;
-  hb_buffer_t *buf;
-  buf = hb_buffer_create();
-  hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="2"><p>
-        Guess the script, language and direction of the buffer.
-      </p></li></ol></div>
-<pre class="programlisting">
-  hb_buffer_guess_segment_properties(buf);
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="3"><p>
-        Create a face and a font, using FreeType for now.
-      </p></li></ol></div>
-<pre class="programlisting">
-  #include &lt;hb-ft.h&gt;
-  FT_New_Face(ft_library, font_path, index, &amp;face)
-  hb_font_t *font = hb_ft_font_create(face);
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="4"><p>
-        Shape!
-      </p></li></ol></div>
-<pre class="programlisting">
-  hb_shape(font, buf, NULL, 0);
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="5"><p>
-        Get the glyph and position information.
-      </p></li></ol></div>
-<pre class="programlisting">
-  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);
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="6"><p>
-        Iterate over each glyph.
-      </p></li></ol></div>
-<pre class="programlisting">
-  for (i = 0; i &lt; glyph_count; ++i) {
-    glyphid = glyph_info[i].codepoint;
-    x_offset = glyph_pos[i].x_offset / 64.0;
-    y_offset = glyph_pos[i].y_offset / 64.0;
-    x_advance = glyph_pos[i].x_advance / 64.0;
-    y_advance = glyph_pos[i].y_advance / 64.0;
-    draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
-    cursor_x += x_advance;
-    cursor_y += y_advance;
-  }
-</pre>
-<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem" value="7"><p>
-        Tidy up.
-      </p></li></ol></div>
-<pre class="programlisting">
-  hb_buffer_destroy(buf);
-  hb_font_destroy(hb_ft_font);
-</pre>
-<div class="section">
-<div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="what-harfbuzz-doesnt-do"></a>What HarfBuzz doesn't do</h2></div></div></div>
-<p>
-      The code above will take a UTF8 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.
-    </p>
-<p>
-      If you are implementing a text layout engine you may have other
-      responsibilities, that HarfBuzz will not help you with:
-    </p>
-<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
-<li class="listitem">
-<p>
-          HarfBuzz won't help you with bidirectionality. If you want to
-          lay out text with mixed Hebrew and English, you will need to
-          ensure that the buffer provided to HarfBuzz has those
-          characters in the correct layout order. This will be different
-          from the logical order in which the Unicode text is stored. In
-          other words, the user will hit the keys in the following
-          sequence:
-        </p>
-<pre class="programlisting">
-A B C [space] ג ב א [space] D E F
-        </pre>
-<p>
-          but will expect to see in the output:
-        </p>
-<pre class="programlisting">
-ABC אבג DEF
-        </pre>
-<p>
-          This reordering is called <span class="emphasis"><em>bidi processing</em></span>
-          ("bidi" is short for bidirectional), and there's an
-          algorithm as an annex to the Unicode Standard which tells you how
-          to reorder a string from logical order into presentation order.
-          Before sending your string to HarfBuzz, you may need to apply the
-          bidi algorithm to it. Libraries such as ICU and fribidi can do
-          this for you.
-        </p>
-</li>
-<li class="listitem"><p>
-          HarfBuzz won't help you with text that contains different font
-          properties. For instance, if you have the string "a
-          <span class="emphasis"><em>huge</em></span> breakfast", and you expect
-          "huge" to be italic, you will need to send three
-          strings to HarfBuzz: <code class="literal">a</code>, in your Roman font;
-          <code class="literal">huge</code> using your italic font; and
-          <code class="literal">breakfast</code> using your Roman font again.
-          Similarly if you change font, font size, script, language or
-          direction within your string, you will need to shape each run
-          independently and then output them independently. HarfBuzz
-          expects to shape a run of characters sharing the same
-          properties.
-        </p></li>
-<li class="listitem">
-<p>
-          HarfBuzz won't help you with line breaking, hyphenation or
-          justification. As mentioned above, it lays out the string
-          along a <span class="emphasis"><em>single line</em></span> 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.
-        </p>
-<p>
-          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. If you
-          want to layout text in paragraphs, you will probably want to send
-          each word of your text to HarfBuzz to determine its shaped width
-          after glyph substitutions, then work out how many words will fit
-          on a line, and then finally output each word of the line separated
-          by a space of the correct size to fully justify the paragraph.
-        </p>
-</li>
-</ul></div>
-<p>
-      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 - what you then do with the glyphs that your font
-      returns is up to you. The example we saw above enough to get us
-      started using HarfBuzz. Now we are going to use the remainder of
-      HarfBuzz's API to refine that example and improve our text shaping
-      capabilities.
-    </p>
-</div>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
index 9346b33..c989d46 100644 (file)
Binary files a/docs/html/home.png and b/docs/html/home.png differ
index 8f72dcb..7d9e404 100644 (file)
@@ -4,10 +4,10 @@
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>HarfBuzz Manual: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<meta name="description" content="HarfBuzz  HarfBuzz is an OpenType text shaping engine. The current HarfBuzz codebase, formerly known as harfbuzz-ng, is versioned 1.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. The canonical source tree is available here. Also available on github. See for release tarballs. The old HarfBuzz codebase, these days known as harfbuzz-old, was derived from FreeType, Pango, and Qt and is available here. It is not actively developed or maintained, and is extremely buggy. All users are encouraged to switch over to the new HarfBuzz as soon as possible. There are no release tarballs of old HarfBuzz whatsoever.">
+<meta name="description" content="HarfBuzz  HarfBuzz is an OpenType text shaping engine. Using the HarfBuzz library allows programs to convert a sequence of Unicode input into properly formatted and positioned glyph output—for any writing system and language. The canonical source-code tree is available at github.com/harfbuzz/harfbuzz and is also available at cgit.freedesktop.org/harfbuzz. See for release tarballs.">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="next" href="pt01.html" title="Part I. User's manual">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <div align="center"><img src="HarfBuzz.png" align="middle"></div>
 <p>
         HarfBuzz is an <a class="ulink" href="http://www.microsoft.com/typography/otspec/" target="_top">OpenType</a>
-        text shaping engine.
+        text shaping engine. Using the HarfBuzz library allows
+       programs to convert a sequence of Unicode input into
+       properly formatted and positioned glyph output—for any writing
+       system and language.
       </p>
 <p>
-        The current HarfBuzz codebase, formerly known as harfbuzz-ng, is
-        versioned 1.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. The canonical
-        source tree is available
-        <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz/" target="_top">here</a>.
-        Also available on
-        <a class="ulink" href="https://github.com/harfbuzz/harfbuzz" target="_top">github</a>.
-        See <a class="xref" href="install-harfbuzz.html#download" title="Download">Download</a> for release tarballs.
-      </p>
-<p>
-        The old HarfBuzz codebase, these days known as harfbuzz-old, was
-        derived from <a class="ulink" href="http://freetype.org/" target="_top">FreeType</a>,
-        <a class="ulink" href="http://pango.org/" target="_top">Pango</a>, and
-        <a class="ulink" href="http://qt-project.org/" target="_top">Qt</a> and is available
-        <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz.old/" target="_top">here</a>.
-        It is not actively developed or maintained, and is extremely buggy. All
-        users are encouraged to switch over to the new HarfBuzz as soon as
-        possible.  There are no release tarballs of old HarfBuzz whatsoever.
+       The canonical source-code tree is available at
+        <a class="ulink" href="https://github.com/harfbuzz/harfbuzz" target="_top">github.com/harfbuzz/harfbuzz</a>
+        and is also available at
+        <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz/" target="_top">cgit.freedesktop.org/harfbuzz</a>.
+       See <a class="xref" href="install-harfbuzz.html#download" title="Downloading HarfBuzz">Downloading HarfBuzz</a> for
+       release tarballs.
       </p>
 </div></div>
 </div>
 <dd><dl>
 <dt><span class="chapter"><a href="what-is-harfbuzz.html">What is HarfBuzz?</a></span></dt>
 <dd><dl>
-<dt><span class="section"><a href="what-is-harfbuzz.html#why-do-i-need-it">Why do I need it?</a></span></dt>
+<dt><span class="section"><a href="what-is-harfbuzz.html#what-is-text-shaping">What is text shaping?</a></span></dt>
+<dt><span class="section"><a href="why-do-i-need-a-shaping-engine.html">Why do I need a shaping engine?</a></span></dt>
+<dt><span class="section"><a href="ch01s03.html">What does HarfBuzz do?</a></span></dt>
+<dt><span class="section"><a href="what-harfbuzz-doesnt-do.html">What HarfBuzz doesn't do</a></span></dt>
 <dt><span class="section"><a href="why-is-it-called-harfbuzz.html">Why is it called HarfBuzz?</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="install-harfbuzz.html">Install HarfBuzz</a></span></dt>
+<dt><span class="chapter"><a href="install-harfbuzz.html">Installing HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="install-harfbuzz.html#download">Downloading HarfBuzz</a></span></dt>
+<dt><span class="section"><a href="building.html">Building HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="building.html#building.linux">Building on Linux</a></span></dt>
+<dt><span class="section"><a href="building.html#building.windows">Building on Windows</a></span></dt>
+<dt><span class="section"><a href="building.html#building.macos">Building on macOS</a></span></dt>
+<dt><span class="section"><a href="building.html#configuration">Configuration options</a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="getting-started.html">Getting started with HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="getting-started.html#id-1.2.4.2">An overview of the HarfBuzz shaping API</a></span></dt>
+<dt><span class="section"><a href="ch03s02.html">Terminology</a></span></dt>
+<dt><span class="section"><a href="ch03s03.html">A simple shaping example</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="shaping-concepts.html">Shaping concepts</a></span></dt>
 <dd><dl>
-<dt><span class="section"><a href="install-harfbuzz.html#download">Download</a></span></dt>
-<dt><span class="section"><a href="building.html">Building</a></span></dt>
+<dt><span class="section"><a href="shaping-concepts.html#text-shaping-concepts">Text shaping</a></span></dt>
+<dt><span class="section"><a href="complex-scripts.html">Complex scripts</a></span></dt>
+<dt><span class="section"><a href="shaping-operations.html">Shaping operations</a></span></dt>
+<dt><span class="section"><a href="unicode-character-categories.html">Unicode character categories</a></span></dt>
+<dt><span class="section"><a href="text-runs.html">Text runs</a></span></dt>
+<dt><span class="section"><a href="opentype-shaping-models.html">OpenType shaping models</a></span></dt>
+<dt><span class="section"><a href="graphite-shaping.html">Graphite shaping</a></span></dt>
+<dt><span class="section"><a href="aat-shaping.html">AAT shaping</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="hello-harfbuzz.html">Hello, HarfBuzz</a></span></dt>
-<dd><dl><dt><span class="section"><a href="hello-harfbuzz.html#what-harfbuzz-doesnt-do">What HarfBuzz doesn't do</a></span></dt></dl></dd>
 <dt><span class="chapter"><a href="buffers-language-script-and-direction.html">Buffers, language, script and direction</a></span></dt>
 <dd><dl>
 <dt><span class="section"><a href="buffers-language-script-and-direction.html#creating-and-destroying-buffers">Creating and destroying buffers</a></span></dt>
 <dt><span class="section"><a href="using-harfbuzzs-native-opentype-implementation.html">Using HarfBuzz's native OpenType implementation</a></span></dt>
 <dt><span class="section"><a href="using-your-own-font-functions.html">Using your own font functions</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="clusters.html"></a></span></dt>
+<dt><span class="chapter"><a href="clusters.html">Clusters</a></span></dt>
 <dd><dl>
-<dt><span class="sect1"><a href="clusters.html#clusters">Clusters</a></span></dt>
-<dt><span class="sect1"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="level-2.html">Level 2</a></span></dt>
+<dt><span class="section"><a href="clusters.html#clusters-and-shaping">Clusters and shaping</a></span></dt>
+<dt><span class="section"><a href="working-with-harfbuzz-clusters.html">Working with HarfBuzz clusters</a></span></dt>
+<dt><span class="section"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="level-2.html">Level 2</a></span></dt>
 <dd><dl>
-<dt><span class="sect2"><a href="level-2.html#ligatures-with-combining-marks">Ligatures with combining marks</a></span></dt>
-<dt><span class="sect2"><a href="level-2.html#reordering">Reordering</a></span></dt>
+<dt><span class="section"><a href="level-2.html#ligatures-with-combining-marks-in-level-2">Ligatures with combining marks in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#reordering-in-level-2">Reordering in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#other-considerations-in-level-2">Other considerations in level 2</a></span></dt>
 </dl></dd>
 </dl></dd>
 <dt><span class="chapter"><a href="shaping-and-shape-plans.html">Shaping and shape plans</a></span></dt>
 </dl></dd>
 <dt><span class="part"><a href="pt02.html">II. Reference manual</a></span></dt>
 <dd><dl>
-<dt><span class="chapter"><a href="ch08.html">HarfBuzz API</a></span></dt>
+<dt><span class="chapter"><a href="ch09.html">Core API</a></span></dt>
 <dd><dl>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb.html">hb</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"> — Binary data containers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-buffer.html">hb-buffer</a></span><span class="refpurpose"> — Input and output buffers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"> — Common data types</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-Buffers.html">Buffers</a></span><span class="refpurpose"> — Input and output buffers</span>
+<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"> — Deprecated API</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"> — Font face objects</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"> — Font objects</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-map.html">hb-map</a></span><span class="refpurpose"> — Object representing integer to integer mapping</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-Shaping.html">Shaping</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
+<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"> — Object representing a set of integers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"> — Object representing a shaping plan</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape.html">hb-shape</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"> — Unicode character property access</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot.html">hb-ot</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"> — Information about the version of HarfBuzz in use</span>
+</dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch10.html">OpenType API</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-color.html">hb-ot-color</a></span><span class="refpurpose"> — OpenType Color Fonts</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"> — OpenType font implementation</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-tag.html">hb-ot-tag</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"> — OpenType Layout</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"> — OpenType Math information</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-name.html">hb-ot-name</a></span><span class="refpurpose"> — OpenType font name information</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"> — OpenType shaping support</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-var.html">hb-ot-var</a></span><span class="refpurpose"> — OpenType Font Variations</span>
 </dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch11.html">Apple Advanced Typography API</a></span></dt>
+<dd><dl><dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-aat-layout.html">hb-aat-layout</a></span><span class="refpurpose"> — Apple Advanced Typography Layout</span>
+</dt></dl></dd>
+<dt><span class="chapter"><a href="ch12.html">Integration API</a></span></dt>
+<dd><dl>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"> — CoreText integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"> — FreeType integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"> — GLib integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"> — GObject integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"> — Graphite2 integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"> — ICU integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"> — Windows integration</span>
 </dt>
 </dl></dd>
-<dt><span class="chapter"><a href="object-tree.html">Object Hierarchy</a></span></dt>
 <dt><span class="index"><a href="api-index-full.html">API Index</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-2.html">Index of new symbols in 0.9.2</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-5.html">Index of new symbols in 0.9.5</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-7.html">Index of new symbols in 0.9.7</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-8.html">Index of new symbols in 0.9.8</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-10.html">Index of new symbols in 0.9.10</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-11.html">Index of new symbols in 0.9.11</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-20.html">Index of new symbols in 0.9.20</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-22.html">Index of new symbols in 0.9.22</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-28.html">Index of new symbols in 0.9.28</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-30.html">Index of new symbols in 0.9.30</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-31.html">Index of new symbols in 0.9.31</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-38.html">Index of new symbols in 0.9.38</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-39.html">Index of new symbols in 0.9.39</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-41.html">Index of new symbols in 0.9.41</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-42.html">Index of new symbols in 0.9.42</a></span></dt>
-<dt><span class="index"><a href="api-index-1-0-5.html">Index of new symbols in 1.0.5</a></span></dt>
-<dt><span class="index"><a href="api-index-1-1-2.html">Index of new symbols in 1.1.2</a></span></dt>
-<dt><span class="index"><a href="api-index-1-1-3.html">Index of new symbols in 1.1.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-2-3.html">Index of new symbols in 1.2.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-3-3.html">Index of new symbols in 1.3.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-4-2.html">Index of new symbols in 1.4.2</a></span></dt>
-<dt><span class="index"><a href="api-index-1-4-3.html">Index of new symbols in 1.4.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-5-0.html">Index of new symbols in 1.5.0</a></span></dt>
-<dt><span class="index"><a href="api-index-1-6-0.html">Index of new symbols in 1.6.0</a></span></dt>
 <dt><span class="index"><a href="deprecated-api-index.html">Index of deprecated API</a></span></dt>
+<dt><span class="index"><a href="api-index-2-1-0.html">Index of new symbols in 2.1.0</a></span></dt>
+<dt><span class="index"><a href="api-index-2-0-0.html">Index of new symbols in 2.0.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-9-0.html">Index of new symbols in 1.9.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-6.html">Index of new symbols in 1.8.6</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-5.html">Index of new symbols in 1.8.5</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-1.html">Index of new symbols in 1.8.1</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-0.html">Index of new symbols in 1.8.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-7-7.html">Index of new symbols in 1.7.7</a></span></dt>
+<dt><span class="index"><a href="api-index-1-7-5.html">Index of new symbols in 1.7.5</a></span></dt>
+<dt><span class="index"><a href="api-index-1-6-0.html">Index of new symbols in 1.6.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-5-0.html">Index of new symbols in 1.5.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-3.html">Index of new symbols in 1.4.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-2.html">Index of new symbols in 1.4.2</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-0.html">Index of new symbols in 1.4.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-3-3.html">Index of new symbols in 1.3.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-2-3.html">Index of new symbols in 1.2.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-1-3.html">Index of new symbols in 1.1.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-1-2.html">Index of new symbols in 1.1.2</a></span></dt>
+<dt><span class="index"><a href="api-index-1-0-5.html">Index of new symbols in 1.0.5</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-42.html">Index of new symbols in 0.9.42</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-41.html">Index of new symbols in 0.9.41</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-39.html">Index of new symbols in 0.9.39</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-38.html">Index of new symbols in 0.9.38</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-31.html">Index of new symbols in 0.9.31</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-30.html">Index of new symbols in 0.9.30</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-28.html">Index of new symbols in 0.9.28</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-22.html">Index of new symbols in 0.9.22</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-20.html">Index of new symbols in 0.9.20</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-11.html">Index of new symbols in 0.9.11</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-10.html">Index of new symbols in 0.9.10</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-8.html">Index of new symbols in 0.9.8</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-7.html">Index of new symbols in 0.9.7</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-5.html">Index of new symbols in 0.9.5</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-2.html">Index of new symbols in 0.9.2</a></span></dt>
 <dt><span class="glossary"><a href="annotation-glossary.html">Annotation Glossary</a></span></dt>
 </dl></dd>
 </dl></div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 019915b..940cf1a 100644 (file)
@@ -2,13 +2,13 @@
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Install HarfBuzz: HarfBuzz Manual</title>
+<title>Installing HarfBuzz: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt01.html" title="Part I. User's manual">
 <link rel="prev" href="why-is-it-called-harfbuzz.html" title="Why is it called HarfBuzz?">
-<link rel="next" href="building.html" title="Building">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="building.html" title="Building HarfBuzz">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 </tr></table>
 <div class="chapter">
 <div class="titlepage"><div><div><h2 class="title">
-<a name="install-harfbuzz"></a>Install HarfBuzz</h2></div></div></div>
+<a name="install-harfbuzz"></a>Installing HarfBuzz</h2></div></div></div>
 <div class="toc"><dl class="toc">
-<dt><span class="section"><a href="install-harfbuzz.html#download">Download</a></span></dt>
-<dt><span class="section"><a href="building.html">Building</a></span></dt>
+<dt><span class="section"><a href="install-harfbuzz.html#download">Downloading HarfBuzz</a></span></dt>
+<dt><span class="section"><a href="building.html">Building HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="building.html#building.linux">Building on Linux</a></span></dt>
+<dt><span class="section"><a href="building.html#building.windows">Building on Windows</a></span></dt>
+<dt><span class="section"><a href="building.html#building.macos">Building on macOS</a></span></dt>
+<dt><span class="section"><a href="building.html#configuration">Configuration options</a></span></dt>
+</dl></dd>
 </dl></div>
 <div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="download"></a>Download</h2></div></div></div>
+<a name="download"></a>Downloading HarfBuzz</h2></div></div></div>
 <p>
-      For tarball releases of HarfBuzz, look
-      <a class="ulink" href="http://www.freedesktop.org/software/harfbuzz/release/" target="_top">here</a>.
-      At the same place you will
-      also find Win32 binary bundles that include libharfbuzz DLL, hb-view.exe,
-      hb-shape.exe, and all dependencies.
+      The HarfBuzz source code is hosted at <a class="ulink" href="https://github.com/harfbuzz/harfbuzz" target="_top">github.com/harfbuzz/harfbuzz</a>. The
+      same source tree is also available at the
+      <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz/" target="_top">Freedesktop.org</a>
+      site.
     </p>
 <p>
-      The canonical source tree is available
-      <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz/" target="_top">here</a>.
-      Also available on <a class="ulink" href="https://github.com/harfbuzz/harfbuzz" target="_top">github</a>.
+      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 <a class="ulink" href="https://github.com/harfbuzz/harfbuzz" target="_top">github.com/harfbuzz/harfbuzz/releases</a>
+      or from 
+      <a class="ulink" href="http://www.freedesktop.org/software/harfbuzz/release/" target="_top">Freedesktop.org</a>.
     </p>
 <p>
-      The API that comes with <code class="filename">hb.h</code> will
-      not change incompatibly. Other, peripheral, headers are more likely to go
-      through minor modifications, but again, will do our best to never change
-      API in an incompatible way. We will never break the ABI.
+      Release notes are posted with each new release to provide an
+      overview of the changes. The project <a class="ulink" href="https://github.com/harfbuzz/harfbuzz/issues" target="_top">tracks bug
+      reports and other issues</a> on GitHub. Discussion and
+      questions are welcome on the <a class="ulink" href="http://freedesktop.org/mailman/listinfo/harfbuzz/" target="_top">HarfBuzz
+      mailing list</a>.
     </p>
 <p>
-      If you are not sure whether Pango or HarfBuzz is right for you, read
-      <a class="ulink" href="http://mces.blogspot.in/2009/11/pango-vs-harfbuzz.html" target="_top">this</a>.
+      The API included in the <code class="filename">hb.h</code> 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 <span class="emphasis"><em>never</em></span> break the ABI. 
     </p>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 3269393..b1148fb 100644 (file)
Binary files a/docs/html/left-insensitive.png and b/docs/html/left-insensitive.png differ
index 2abde03..c164913 100644 (file)
Binary files a/docs/html/left.png and b/docs/html/left.png differ
index 23410dc..3e67349 100644 (file)
@@ -5,10 +5,10 @@
 <title>Level 2: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="clusters.html" title="">
+<link rel="up" href="clusters.html" title="Clusters">
 <link rel="prev" href="the-distinction-between-levels-0-and-1.html" title="The distinction between levels 0 and 1">
 <link rel="next" href="shaping-and-shape-plans.html" title="Shaping and shape plans">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="p" href="the-distinction-between-levels-0-and-1.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="shaping-and-shape-plans.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
-<div class="sect1">
+<div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="level-2"></a>Level 2</h2></div></div></div>
 <p>
-    Level 2 is a different beast from levels 0 and 1. It is simple to
-    describe, but hard to make sense of. It simply doesn't do any
-    cluster merging whatsoever. When things ligate or otherwise multiple
-    glyphs turn into one, the cluster value of the first glyph is
-    retained.
-  </p>
-<p>
-    Here are a few examples of why processing cluster values produced at
-    this level might be tricky:
-  </p>
-<div class="sect2">
-<div class="titlepage"><div><div><h3 class="title">
-<a name="ligatures-with-combining-marks"></a>Ligatures with combining marks</h3></div></div></div>
+      HarfBuzz's level 2 cluster behavior uses a significantly
+      different model than that of level 0 and level 1.
+    </p>
 <p>
-      Imagine capital letters are bases and lower case letters are
-      combining marks. With an input sequence like this:
+      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.
     </p>
-<pre class="programlisting">
-  A,a,B,b,C,c
-  0,1,2,3,4,5
-</pre>
 <p>
-      if <code class="literal">A,B,C</code> ligate, then here are the cluster
-      values one would get under the various levels:
+      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.
     </p>
 <p>
-      level 0:
+      Only one shaping operation directly affects clusters when using
+      level 2:
     </p>
-<pre class="programlisting">
-  ABC,a,b,c
-  0  ,0,0,0
-</pre>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
+         When a cluster <span class="emphasis"><em>decomposes</em></span>, all of the
+         resulting child clusters inherit as their cluster value the
+         cluster value of the parent cluster.
+       </p></li></ul></div>
 <p>
-      level 1:
+      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.
     </p>
-<pre class="programlisting">
-  ABC,a,b,c
-  0  ,0,0,5
-</pre>
 <p>
-      level 2:
+      This occurrence sounds similar to a cluster merge, but it is
+      different. In particular, no subsequent characters —
+      including marks and modifiers — are affected. They retain
+      their previous cluster values. 
     </p>
-<pre class="programlisting">
-  ABC,a,b,c
-  0  ,1,3,5
-</pre>
-<p>
-      Making sense of the last example is the hardest for a client,
-      because there is nothing in the cluster values to suggest that
-      <code class="literal">B</code> and <code class="literal">C</code> ligated with
-      <code class="literal">A</code>.
+<p>
+      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. 
     </p>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="ligatures-with-combining-marks-in-level-2"></a>Ligatures with combining marks in level 2</h3></div></div></div>
+<p>
+       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.
+      </p>
+<p>
+       Let us start with an input sequence with the following
+       characters (top row) and initial cluster values (bottom row):
+      </p>
+<pre class="programlisting">
+       A,acute,B,breve,C,circumflex
+       0,1    ,2,3    ,4,5
+      </pre>
+<p>
+       If the sequence <code class="literal">A,B,C</code> forms a ligature,
+       then these are the cluster values HarfBuzz will return under
+       the various cluster levels:
+      </p>
+<p>
+       Level 0:
+      </p>
+<pre class="programlisting">
+       ABC,acute,breve,circumflex
+       0  ,0    ,0    ,0
+      </pre>
+<p>
+       Level 1:
+      </p>
+<pre class="programlisting">
+       ABC,acute,breve,circumflex
+       0  ,0    ,0    ,5
+      </pre>
+<p>
+       Level 2:
+      </p>
+<pre class="programlisting">
+       ABC,acute,breve,circumflex
+       0  ,1    ,3    ,5
+      </pre>
+<p>
+       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 <code class="literal">B</code> and <code class="literal">C</code>
+       formed a ligature with <code class="literal">A</code>.
+      </p>
+<p>
+       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. 
+      </p>
 </div>
-<div class="sect2">
+<div class="section">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="reordering"></a>Reordering</h3></div></div></div>
+<a name="reordering-in-level-2"></a>Reordering in level 2</h3></div></div></div>
 <p>
-      Another tricky case is when things reorder. Under level 2:
-    </p>
+       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):
+      </p>
 <pre class="programlisting">
-  A,B,C,D,E
-  0,1,2,3,4
-</pre>
+       A,B,C,D,E
+       0,1,2,3,4
+      </pre>
 <p>
-      Now imagine <code class="literal">D</code> moves before
-      <code class="literal">B</code>:
-    </p>
+       Now imagine <code class="literal">D</code> moves before
+       <code class="literal">B</code> in a reordering operation. The cluster
+       values will then be:
+      </p>
 <pre class="programlisting">
-  A,D,B,C,E
-  0,3,1,2,4
-</pre>
+       A,D,B,C,E
+       0,3,1,2,4
+      </pre>
 <p>
-      Now, if <code class="literal">D</code> ligates with <code class="literal">B</code>, we
-      get:
-    </p>
+       Next, if <code class="literal">D</code> forms a ligature with
+       <code class="literal">B</code>, the output is:
+      </p>
 <pre class="programlisting">
-  A,DB,C,E
-  0,3 ,2,4
-</pre>
-<p>
-      In a different scenario, <code class="literal">A</code> and
-      <code class="literal">B</code> could have ligated
-      <span class="emphasis"><em>before</em></span> <code class="literal">D</code> reordered; that
-      would have resulted in:
-    </p>
+       A,DB,C,E
+       0,3 ,2,4
+      </pre>
+<p>
+       However, in a different scenario, in which the shaping rules
+       of the script instead caused <code class="literal">A</code> and
+       <code class="literal">B</code> to form a ligature
+       <span class="emphasis"><em>before</em></span> the <code class="literal">D</code> reordered, the
+       result would be:
+      </p>
 <pre class="programlisting">
-  AB,D,C,E
-  0 ,3,2,4   
-</pre>
+       AB,D,C,E
+       0 ,3,2,4   
+      </pre>
 <p>
-      There's no way to differentiate between these two scenarios based
-      on the cluster numbers alone.
-    </p>
+       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.
+      </p>
+</div>
+<div class="section">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="other-considerations-in-level-2"></a>Other considerations in level 2</h3></div></div></div>
 <p>
-      Another problem happens with ligatures under level 2 if the
-      direction of the text is forced to opposite of its natural
-      direction (e.g. left-to-right Arabic). But that's too much of a
-      corner case to worry about.
-    </p>
+       There may be other problems encountered with ligatures under
+       level 2, such as if the direction of the text is forced to
+       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.
+      </p>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/object-tree.html b/docs/html/object-tree.html
deleted file mode 100644 (file)
index 80d35bc..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Object Hierarchy: HarfBuzz Manual</title>
-<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
-<link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="pt02.html" title="Part II. Reference manual">
-<link rel="prev" href="harfbuzz-hb-gobject.html" title="hb-gobject">
-<link rel="next" href="api-index-full.html" title="API Index">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
-<link rel="stylesheet" href="style.css" type="text/css">
-</head>
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
-<td width="100%" align="left" class="shortcuts"></td>
-<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
-<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="harfbuzz-hb-gobject.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="api-index-full.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
-</tr></table>
-<div class="chapter">
-<div class="titlepage"><div><div><h2 class="title">
-<a name="object-tree"></a>Object Hierarchy</h2></div></div></div>
-<pre class="screen">
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-blob.html#hb-blob-t">hb_blob_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-t">hb_buffer_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-face.html#hb-face-t">hb_face_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Shaping.html#hb-feature-t">hb_feature_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-font.html#hb-font-funcs-t">hb_font_funcs_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-font.html#hb-font-t">hb_font_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-glyph-info-t">hb_glyph_info_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-glyph-position-t">hb_glyph_position_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-part-t">hb_ot_math_glyph_part_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-variant-t">hb_ot_math_glyph_variant_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-segment-properties-t">hb_segment_properties_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-set.html#hb-set-t">hb_set_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-shape-plan.html#hb-shape-plan-t">hb_shape_plan_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-funcs-t">hb_unicode_funcs_t</a>
-    <span class="lineart">╰──</span> <a class="link" href="harfbuzz-hb-common.html#hb-user-data-key-t">hb_user_data_key_t</a>
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-cluster-level-t" title="enum hb_buffer_cluster_level_t">hb_buffer_cluster_level_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-content-type-t" title="enum hb_buffer_content_type_t">hb_buffer_content_type_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-format-t" title="enum hb_buffer_serialize_format_t">hb_buffer_serialize_format_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-common.html#hb-direction-t" title="enum hb_direction_t">hb_direction_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-blob.html#hb-memory-mode-t" title="enum hb_memory_mode_t">hb_memory_mode_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-ot-layout.html#hb-ot-layout-glyph-class-t" title="enum hb_ot_layout_glyph_class_t">hb_ot_layout_glyph_class_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-constant-t" title="enum hb_ot_math_constant_t">hb_ot_math_constant_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-kern-t" title="enum hb_ot_math_kern_t">hb_ot_math_kern_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-common.html#hb-script-t" title="enum hb_script_t">hb_script_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-combining-class-t" title="enum hb_unicode_combining_class_t">hb_unicode_combining_class_t</a>
-    <span class="lineart">╰──</span> <a class="link" href="harfbuzz-hb-unicode.html#hb-unicode-general-category-t" title="enum hb_unicode_general_category_t">hb_unicode_general_category_t</a>
-    <a href="/home/behdad/.local/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-diff-flags-t" title="enum hb_buffer_diff_flags_t">hb_buffer_diff_flags_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-flags-t" title="enum hb_buffer_flags_t">hb_buffer_flags_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-buffer-serialize-flags-t" title="enum hb_buffer_serialize_flags_t">hb_buffer_serialize_flags_t</a>
-    <span class="lineart">├──</span> <a class="link" href="harfbuzz-Buffers.html#hb-glyph-flags-t" title="enum hb_glyph_flags_t">hb_glyph_flags_t</a>
-    <span class="lineart">╰──</span> <a class="link" href="harfbuzz-hb-ot-math.html#hb-ot-math-glyph-part-flags-t" title="enum hb_ot_math_glyph_part_flags_t">hb_ot_math_glyph_part_flags_t</a>
-</pre>
-</div>
-<div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/docs/html/opentype-shaping-models.html b/docs/html/opentype-shaping-models.html
new file mode 100644 (file)
index 0000000..46b9e2b
--- /dev/null
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>OpenType shaping models: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="text-runs.html" title="Text runs">
+<link rel="next" href="graphite-shaping.html" title="Graphite shaping">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="text-runs.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="graphite-shaping.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="opentype-shaping-models"></a>OpenType shaping models</h2></div></div></div>
+<p>
+      OpenType provides shaping models for the following scripts:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>
+         The <span class="emphasis"><em>default</em></span> shaping model handles all
+         non-complex scripts, and may also be used as a fallback for
+         handling unrecognized scripts.
+       </p></li>
+<li class="listitem">
+<p>
+         The <span class="emphasis"><em>Indic</em></span> shaping model handles the Indic
+         scripts Bengali, Devanagari, Gujarati, Gurmukhi, Kannada,
+         Malayalam, Oriya, Tamil, Telugu, and Sinhala.
+       </p>
+<p>
+         The Indic shaping model was revised significantly in
+         2005. To denote the change, a new set of <span class="emphasis"><em>script
+         tags</em></span> 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.
+       </p>
+</li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Arabic</em></span> shaping model supports
+         Arabic, Mongolian, N'Ko, Syriac, and several other connected
+         or cursive scripts.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Thai/Lao</em></span> shaping model supports
+         the Thai and Lao scripts.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Khmer</em></span> shaping model supports the
+         Khmer script.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Myanmar</em></span> shaping model supports the
+         Myanmar (or Burmese) script.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Tibetan</em></span> shaping model supports the
+         Tibetan script.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Hangul</em></span> shaping model supports the
+         Hangul script.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Hebrew</em></span> shaping model supports the
+         Hebrew script.
+       </p></li>
+<li class="listitem"><p>
+         The <span class="emphasis"><em>Universal Shaping Engine</em></span> (USE)
+         shaping model supports complex 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. 
+       </p></li>
+<li class="listitem"><p>
+         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 <span class="emphasis"><em>Emoji</em></span> shaping, which
+         may involve variation-selector sequences and glyph
+         substitution. Emoji shaping is handled by the default
+         shaping model.
+       </p></li>
+</ul></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 89a9f35..5d81872 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="shaping-and-shape-plans.html" title="Shaping and shape plans">
 <link rel="prev" href="shaping-and-shape-plans.html" title="Shaping and shape plans">
 <link rel="next" href="pt02.html" title="Part II. Reference manual">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 5cc9f2c..2aee80e 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="index.html" title="HarfBuzz Manual">
 <link rel="prev" href="index.html" title="HarfBuzz Manual">
 <link rel="next" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <dl class="toc">
 <dt><span class="chapter"><a href="what-is-harfbuzz.html">What is HarfBuzz?</a></span></dt>
 <dd><dl>
-<dt><span class="section"><a href="what-is-harfbuzz.html#why-do-i-need-it">Why do I need it?</a></span></dt>
+<dt><span class="section"><a href="what-is-harfbuzz.html#what-is-text-shaping">What is text shaping?</a></span></dt>
+<dt><span class="section"><a href="why-do-i-need-a-shaping-engine.html">Why do I need a shaping engine?</a></span></dt>
+<dt><span class="section"><a href="ch01s03.html">What does HarfBuzz do?</a></span></dt>
+<dt><span class="section"><a href="what-harfbuzz-doesnt-do.html">What HarfBuzz doesn't do</a></span></dt>
 <dt><span class="section"><a href="why-is-it-called-harfbuzz.html">Why is it called HarfBuzz?</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="install-harfbuzz.html">Install HarfBuzz</a></span></dt>
+<dt><span class="chapter"><a href="install-harfbuzz.html">Installing HarfBuzz</a></span></dt>
 <dd><dl>
-<dt><span class="section"><a href="install-harfbuzz.html#download">Download</a></span></dt>
-<dt><span class="section"><a href="building.html">Building</a></span></dt>
+<dt><span class="section"><a href="install-harfbuzz.html#download">Downloading HarfBuzz</a></span></dt>
+<dt><span class="section"><a href="building.html">Building HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="building.html#building.linux">Building on Linux</a></span></dt>
+<dt><span class="section"><a href="building.html#building.windows">Building on Windows</a></span></dt>
+<dt><span class="section"><a href="building.html#building.macos">Building on macOS</a></span></dt>
+<dt><span class="section"><a href="building.html#configuration">Configuration options</a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="getting-started.html">Getting started with HarfBuzz</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="getting-started.html#id-1.2.4.2">An overview of the HarfBuzz shaping API</a></span></dt>
+<dt><span class="section"><a href="ch03s02.html">Terminology</a></span></dt>
+<dt><span class="section"><a href="ch03s03.html">A simple shaping example</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="shaping-concepts.html">Shaping concepts</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="shaping-concepts.html#text-shaping-concepts">Text shaping</a></span></dt>
+<dt><span class="section"><a href="complex-scripts.html">Complex scripts</a></span></dt>
+<dt><span class="section"><a href="shaping-operations.html">Shaping operations</a></span></dt>
+<dt><span class="section"><a href="unicode-character-categories.html">Unicode character categories</a></span></dt>
+<dt><span class="section"><a href="text-runs.html">Text runs</a></span></dt>
+<dt><span class="section"><a href="opentype-shaping-models.html">OpenType shaping models</a></span></dt>
+<dt><span class="section"><a href="graphite-shaping.html">Graphite shaping</a></span></dt>
+<dt><span class="section"><a href="aat-shaping.html">AAT shaping</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="hello-harfbuzz.html">Hello, HarfBuzz</a></span></dt>
-<dd><dl><dt><span class="section"><a href="hello-harfbuzz.html#what-harfbuzz-doesnt-do">What HarfBuzz doesn't do</a></span></dt></dl></dd>
 <dt><span class="chapter"><a href="buffers-language-script-and-direction.html">Buffers, language, script and direction</a></span></dt>
 <dd><dl>
 <dt><span class="section"><a href="buffers-language-script-and-direction.html#creating-and-destroying-buffers">Creating and destroying buffers</a></span></dt>
 <dt><span class="section"><a href="using-harfbuzzs-native-opentype-implementation.html">Using HarfBuzz's native OpenType implementation</a></span></dt>
 <dt><span class="section"><a href="using-your-own-font-functions.html">Using your own font functions</a></span></dt>
 </dl></dd>
-<dt><span class="chapter"><a href="clusters.html"></a></span></dt>
+<dt><span class="chapter"><a href="clusters.html">Clusters</a></span></dt>
 <dd><dl>
-<dt><span class="sect1"><a href="clusters.html#clusters">Clusters</a></span></dt>
-<dt><span class="sect1"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
-<dt><span class="sect1"><a href="level-2.html">Level 2</a></span></dt>
+<dt><span class="section"><a href="clusters.html#clusters-and-shaping">Clusters and shaping</a></span></dt>
+<dt><span class="section"><a href="working-with-harfbuzz-clusters.html">Working with HarfBuzz clusters</a></span></dt>
+<dt><span class="section"><a href="a-clustering-example-for-levels-0-and-1.html">A clustering example for levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="reordering-in-levels-0-and-1.html">Reordering in levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="the-distinction-between-levels-0-and-1.html">The distinction between levels 0 and 1</a></span></dt>
+<dt><span class="section"><a href="level-2.html">Level 2</a></span></dt>
 <dd><dl>
-<dt><span class="sect2"><a href="level-2.html#ligatures-with-combining-marks">Ligatures with combining marks</a></span></dt>
-<dt><span class="sect2"><a href="level-2.html#reordering">Reordering</a></span></dt>
+<dt><span class="section"><a href="level-2.html#ligatures-with-combining-marks-in-level-2">Ligatures with combining marks in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#reordering-in-level-2">Reordering in level 2</a></span></dt>
+<dt><span class="section"><a href="level-2.html#other-considerations-in-level-2">Other considerations in level 2</a></span></dt>
 </dl></dd>
 </dl></dd>
 <dt><span class="chapter"><a href="shaping-and-shape-plans.html">Shaping and shape plans</a></span></dt>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index ac7201f..2dd2ac9 100644 (file)
@@ -7,8 +7,8 @@
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="index.html" title="HarfBuzz Manual">
 <link rel="prev" href="plans-and-caching.html" title="Plans and caching">
-<link rel="next" href="ch08.html" title="HarfBuzz API">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="ch09.html" title="Core API">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><img src="up-insensitive.png" width="16" height="16" border="0"></td>
 <td><a accesskey="p" href="plans-and-caching.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="ch08.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="n" href="ch09.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="part">
 <div class="titlepage"><div>
 <div><h1 class="title">
 <a name="id-1.3"></a>Part II. Reference manual</h1></div>
 <div><p class="releaseinfo">
-        This document is for HarfBuzz 1.8.1
+        This document is for HarfBuzz 2.3.1
 .
         
       </p></div>
 <div class="toc">
 <p><b>Table of Contents</b></p>
 <dl class="toc">
-<dt><span class="chapter"><a href="ch08.html">HarfBuzz API</a></span></dt>
+<dt><span class="chapter"><a href="ch09.html">Core API</a></span></dt>
 <dd><dl>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb.html">hb</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"> — Binary data containers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-buffer.html">hb-buffer</a></span><span class="refpurpose"> — Input and output buffers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-common.html">hb-common</a></span><span class="refpurpose"> — Common data types</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-Buffers.html">Buffers</a></span><span class="refpurpose"> — Input and output buffers</span>
+<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"> — Deprecated API</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-blob.html">hb-blob</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"> — Font face objects</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-face.html">hb-face</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"> — Font objects</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-font.html">hb-font</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-map.html">hb-map</a></span><span class="refpurpose"> — Object representing integer to integer mapping</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-Shaping.html">Shaping</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
+<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"> — Object representing a set of integers</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"> — Object representing a shaping plan</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-deprecated.html">hb-deprecated</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-shape.html">hb-shape</a></span><span class="refpurpose"> — Conversion of text strings into positioned glyphs</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-set.html">hb-set</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-unicode.html">hb-unicode</a></span><span class="refpurpose"> — Unicode character property access</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot.html">hb-ot</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-version.html">hb-version</a></span><span class="refpurpose"> — Information about the version of HarfBuzz in use</span>
 </dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch10.html">OpenType API</a></span></dt>
+<dd><dl>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-color.html">hb-ot-color</a></span><span class="refpurpose"> — OpenType Color Fonts</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-tag.html">hb-ot-tag</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"> — OpenType font implementation</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-font.html">hb-ot-font</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-layout.html">hb-ot-layout</a></span><span class="refpurpose"> — OpenType Layout</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"> — OpenType Math information</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ot-math.html">hb-ot-math</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-name.html">hb-ot-name</a></span><span class="refpurpose"> — OpenType font name information</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-shape-plan.html">hb-shape-plan</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-shape.html">hb-ot-shape</a></span><span class="refpurpose"> — OpenType shaping support</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ot-var.html">hb-ot-var</a></span><span class="refpurpose"> — OpenType Font Variations</span>
 </dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch11.html">Apple Advanced Typography API</a></span></dt>
+<dd><dl><dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-aat-layout.html">hb-aat-layout</a></span><span class="refpurpose"> — Apple Advanced Typography Layout</span>
+</dt></dl></dd>
+<dt><span class="chapter"><a href="ch12.html">Integration API</a></span></dt>
+<dd><dl>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"> — CoreText integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-ft.html">hb-ft</a></span><span class="refpurpose"> — FreeType integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-glib.html">hb-glib</a></span><span class="refpurpose"> — GLib integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"> — GObject integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-coretext.html">hb-coretext</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-graphite2.html">hb-graphite2</a></span><span class="refpurpose"> — Graphite2 integration</span>
 </dt>
 <dt>
-<span class="refentrytitle"><a href="harfbuzz-hb-gobject.html">hb-gobject</a></span><span class="refpurpose"></span>
+<span class="refentrytitle"><a href="harfbuzz-hb-icu.html">hb-icu</a></span><span class="refpurpose"> — ICU integration</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="harfbuzz-hb-uniscribe.html">hb-uniscribe</a></span><span class="refpurpose"> — Windows integration</span>
 </dt>
 </dl></dd>
-<dt><span class="chapter"><a href="object-tree.html">Object Hierarchy</a></span></dt>
 <dt><span class="index"><a href="api-index-full.html">API Index</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-2.html">Index of new symbols in 0.9.2</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-5.html">Index of new symbols in 0.9.5</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-7.html">Index of new symbols in 0.9.7</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-8.html">Index of new symbols in 0.9.8</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-10.html">Index of new symbols in 0.9.10</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-11.html">Index of new symbols in 0.9.11</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-20.html">Index of new symbols in 0.9.20</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-22.html">Index of new symbols in 0.9.22</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-28.html">Index of new symbols in 0.9.28</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-30.html">Index of new symbols in 0.9.30</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-31.html">Index of new symbols in 0.9.31</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-38.html">Index of new symbols in 0.9.38</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-39.html">Index of new symbols in 0.9.39</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-41.html">Index of new symbols in 0.9.41</a></span></dt>
-<dt><span class="index"><a href="api-index-0-9-42.html">Index of new symbols in 0.9.42</a></span></dt>
-<dt><span class="index"><a href="api-index-1-0-5.html">Index of new symbols in 1.0.5</a></span></dt>
-<dt><span class="index"><a href="api-index-1-1-2.html">Index of new symbols in 1.1.2</a></span></dt>
-<dt><span class="index"><a href="api-index-1-1-3.html">Index of new symbols in 1.1.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-2-3.html">Index of new symbols in 1.2.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-3-3.html">Index of new symbols in 1.3.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-4-2.html">Index of new symbols in 1.4.2</a></span></dt>
-<dt><span class="index"><a href="api-index-1-4-3.html">Index of new symbols in 1.4.3</a></span></dt>
-<dt><span class="index"><a href="api-index-1-5-0.html">Index of new symbols in 1.5.0</a></span></dt>
-<dt><span class="index"><a href="api-index-1-6-0.html">Index of new symbols in 1.6.0</a></span></dt>
 <dt><span class="index"><a href="deprecated-api-index.html">Index of deprecated API</a></span></dt>
+<dt><span class="index"><a href="api-index-2-1-0.html">Index of new symbols in 2.1.0</a></span></dt>
+<dt><span class="index"><a href="api-index-2-0-0.html">Index of new symbols in 2.0.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-9-0.html">Index of new symbols in 1.9.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-6.html">Index of new symbols in 1.8.6</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-5.html">Index of new symbols in 1.8.5</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-1.html">Index of new symbols in 1.8.1</a></span></dt>
+<dt><span class="index"><a href="api-index-1-8-0.html">Index of new symbols in 1.8.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-7-7.html">Index of new symbols in 1.7.7</a></span></dt>
+<dt><span class="index"><a href="api-index-1-7-5.html">Index of new symbols in 1.7.5</a></span></dt>
+<dt><span class="index"><a href="api-index-1-6-0.html">Index of new symbols in 1.6.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-5-0.html">Index of new symbols in 1.5.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-3.html">Index of new symbols in 1.4.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-2.html">Index of new symbols in 1.4.2</a></span></dt>
+<dt><span class="index"><a href="api-index-1-4-0.html">Index of new symbols in 1.4.0</a></span></dt>
+<dt><span class="index"><a href="api-index-1-3-3.html">Index of new symbols in 1.3.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-2-3.html">Index of new symbols in 1.2.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-1-3.html">Index of new symbols in 1.1.3</a></span></dt>
+<dt><span class="index"><a href="api-index-1-1-2.html">Index of new symbols in 1.1.2</a></span></dt>
+<dt><span class="index"><a href="api-index-1-0-5.html">Index of new symbols in 1.0.5</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-42.html">Index of new symbols in 0.9.42</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-41.html">Index of new symbols in 0.9.41</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-39.html">Index of new symbols in 0.9.39</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-38.html">Index of new symbols in 0.9.38</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-31.html">Index of new symbols in 0.9.31</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-30.html">Index of new symbols in 0.9.30</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-28.html">Index of new symbols in 0.9.28</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-22.html">Index of new symbols in 0.9.22</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-20.html">Index of new symbols in 0.9.20</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-11.html">Index of new symbols in 0.9.11</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-10.html">Index of new symbols in 0.9.10</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-8.html">Index of new symbols in 0.9.8</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-7.html">Index of new symbols in 0.9.7</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-5.html">Index of new symbols in 0.9.5</a></span></dt>
+<dt><span class="index"><a href="api-index-0-9-2.html">Index of new symbols in 0.9.2</a></span></dt>
 <dt><span class="glossary"><a href="annotation-glossary.html">Annotation Glossary</a></span></dt>
 </dl>
 </div>
+<div class="note">
+<p>
+        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. 
+      </p>
+<p>
+        Prior to 2012, the original HarfBuzz codebase (which, these
+       days, is referred to as <span class="emphasis"><em>harfbuzz-old</em></span>) was 
+        derived from code in <a class="ulink" href="http://freetype.org/" target="_top">FreeType</a>, <a class="ulink" href="http://pango.org/" target="_top">Pango</a>, and 
+        <a class="ulink" href="http://qt-project.org/" target="_top">Qt</a>.
+        It is <span class="emphasis"><em>not</em></span> 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.
+      </p>
+<p>
+       To make this distinction clearer in discussions, the current
+       HarfBuzz codebase is sometimes referred to as
+       <span class="emphasis"><em>harfbuzz-ng</em></span>.
+      </p>
+<p>
+       For reference purposes, the harfbuzz-old source tree is archived 
+        <a class="ulink" href="http://cgit.freedesktop.org/harfbuzz.old/" target="_top">here</a>. There
+       are no release tarballs of harfbuzz-old whatsoever.
+      </p>
+</div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 9b0a47e..2a390b7 100644 (file)
@@ -5,10 +5,10 @@
 <title>Reordering in levels 0 and 1: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="clusters.html" title="">
+<link rel="up" href="clusters.html" title="Clusters">
 <link rel="prev" href="a-clustering-example-for-levels-0-and-1.html" title="A clustering example for levels 0 and 1">
 <link rel="next" href="the-distinction-between-levels-0-and-1.html" title="The distinction between levels 0 and 1">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="p" href="a-clustering-example-for-levels-0-and-1.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="the-distinction-between-levels-0-and-1.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
-<div class="sect1">
+<div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="reordering-in-levels-0-and-1"></a>Reordering in levels 0 and 1</h2></div></div></div>
 <p>
-    Another common operation in the more complex shapers is when things
-    reorder. In those cases, to maintain monotone clusters, HB merges
-    the clusters of everything in the reordering sequence. For example,
-    let's again start with the character sequence:
-  </p>
+      Another common operation in the more complex 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.
+    </p>
+<p>
+      For example, let us again start with the character sequence (top
+      row) and initial cluster values (bottom row):
+    </p>
 <pre class="programlisting">
-   A,B,C,D,E
-   0,1,2,3,4
-</pre>
+      A,B,C,D,E
+      0,1,2,3,4
+    </pre>
 <p>
-    If <code class="literal">D</code> is reordered before <code class="literal">B</code>,
-    then the <code class="literal">B</code>, <code class="literal">C</code>, and
-    <code class="literal">D</code> clusters merge, and we get:
-  </p>
+      If <code class="literal">D</code> is reordered to the position immediately
+      before <code class="literal">B</code>, then HarfBuzz merges the
+      <code class="literal">B</code>, <code class="literal">C</code>, and
+      <code class="literal">D</code> clusters — all the clusters between
+      the final position of the reordered glyph and its original
+      position. This means that we get:
+    </p>
 <pre class="programlisting">
-   A,D,B,C,E
-   0,1,1,1,4
-</pre>
+      A,D,B,C,E
+      0,1,1,1,4
+    </pre>
+<p>
+      as the final cluster sequence.
+    </p>
 <p>
-    This is clearly not ideal, but it is the only sensible way to
-    maintain monotone indices and retain the true relationship between
-    glyphs and characters.
-  </p>
+      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.
+    </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 4c95785..c1efa27 100644 (file)
Binary files a/docs/html/right-insensitive.png and b/docs/html/right-insensitive.png differ
index 76260ec..83361a6 100644 (file)
Binary files a/docs/html/right.png and b/docs/html/right.png differ
index ecc07ee..266dfd7 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
 <link rel="prev" href="adding-text-to-the-buffer.html" title="Adding text to the buffer">
 <link rel="next" href="what-about-the-other-scripts.html" title="What about the other scripts?">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index c3e2029..4aacb0f 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="pt01.html" title="Part I. User's manual">
 <link rel="prev" href="level-2.html" title="Level 2">
 <link rel="next" href="plans-and-caching.html" title="Plans and caching">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -34,6 +34,6 @@
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/shaping-concepts.html b/docs/html/shaping-concepts.html
new file mode 100644 (file)
index 0000000..bfa6a41
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Shaping concepts: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="pt01.html" title="Part I. User's manual">
+<link rel="prev" href="ch03s03.html" title="A simple shaping example">
+<link rel="next" href="complex-scripts.html" title="Complex scripts">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch03s03.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="complex-scripts.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="shaping-concepts"></a>Shaping concepts</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt><span class="section"><a href="shaping-concepts.html#text-shaping-concepts">Text shaping</a></span></dt>
+<dt><span class="section"><a href="complex-scripts.html">Complex scripts</a></span></dt>
+<dt><span class="section"><a href="shaping-operations.html">Shaping operations</a></span></dt>
+<dt><span class="section"><a href="unicode-character-categories.html">Unicode character categories</a></span></dt>
+<dt><span class="section"><a href="text-runs.html">Text runs</a></span></dt>
+<dt><span class="section"><a href="opentype-shaping-models.html">OpenType shaping models</a></span></dt>
+<dt><span class="section"><a href="graphite-shaping.html">Graphite shaping</a></span></dt>
+<dt><span class="section"><a href="aat-shaping.html">AAT shaping</a></span></dt>
+</dl></div>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="text-shaping-concepts"></a>Text shaping</h2></div></div></div>
+<p>
+      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.
+    </p>
+<p>
+      For some writing systems (or <span class="emphasis"><em>scripts</em></span>) 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.
+    </p>
+<p>
+      But, for <span class="emphasis"><em>complex scripts</em></span>, 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.
+    </p>
+<p>
+      The exact rules and necessary operations for a particular script
+      constitute a shaping <span class="emphasis"><em>model</em></span>. 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). 
+    </p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/shaping-operations.html b/docs/html/shaping-operations.html
new file mode 100644 (file)
index 0000000..9e6ff5e
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Shaping operations: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="complex-scripts.html" title="Complex scripts">
+<link rel="next" href="unicode-character-categories.html" title="Unicode character categories">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="complex-scripts.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="unicode-character-categories.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="shaping-operations"></a>Shaping operations</h2></div></div></div>
+<p>
+      Shaping a complex-script 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.
+    </p>
+<p>
+      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 complex-script shaping models. 
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+<p>
+         A <span class="emphasis"><em>reordering</em></span> operation moves a glyph
+         from its original ("logical") position in the sequence to
+         some other ("visual") position.
+       </p>
+<p>
+         The shaping model for a given complex script might involve
+         more than one reordering step.
+       </p>
+</li>
+<li class="listitem"><p>
+         A <span class="emphasis"><em>joining</em></span> operation replaces a glyph
+         with an alternate form that is designed to connect with one
+         or more of the adjacent glyphs in the sequence.
+       </p></li>
+<li class="listitem">
+<p>
+         A contextual <span class="emphasis"><em>substitution</em></span> 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.
+       </p>
+<p>
+         The shaping model for a given complex script might involve
+         multiple contextual-substitution operations, each applying
+         to different target glyphs and patterns, and which are
+         performed in separate steps.
+       </p>
+</li>
+<li class="listitem">
+<p>
+         A contextual <span class="emphasis"><em>positioning</em></span> 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.
+       </p>
+<p>
+         Many contextual positioning operations are used to place
+         <span class="emphasis"><em>mark</em></span> glyphs (such as diacritics, vowel
+         signs, and tone markers) with respect to
+         <span class="emphasis"><em>base</em></span> glyphs. However, some complex
+         scripts may use contextual positioning operations to
+         correctly place base glyphs as well, such as
+         when the script uses <span class="emphasis"><em>stacking</em></span> characters.
+       </p>
+</li>
+</ul></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 4be4ede..3675420 100644 (file)
@@ -30,10 +30,6 @@ body
   vertical-align: top;
 }
 
-span.nowrap {
-  white-space: nowrap;
-}
-
 div.gallery-float
 {
   float: left;
diff --git a/docs/html/text-runs.html b/docs/html/text-runs.html
new file mode 100644 (file)
index 0000000..26804d3
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Text runs: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="unicode-character-categories.html" title="Unicode character categories">
+<link rel="next" href="opentype-shaping-models.html" title="OpenType shaping models">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="unicode-character-categories.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="opentype-shaping-models.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="text-runs"></a>Text runs</h2></div></div></div>
+<p>
+      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).
+    </p>
+<p>
+      For shaping purposes, all real-world text streams must be first
+      segmented into runs that have a uniform set of properties. 
+    </p>
+<p>
+      In particular, shaping models always assume that every codepoint
+      in a text run has the same <span class="emphasis"><em>direction</em></span>,
+      <span class="emphasis"><em>script</em></span> tag, and
+      <span class="emphasis"><em>language</em></span> tag.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 0365f01..cbb7afe 100644 (file)
@@ -5,10 +5,10 @@
 <title>The distinction between levels 0 and 1: HarfBuzz Manual</title>
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
-<link rel="up" href="clusters.html" title="">
+<link rel="up" href="clusters.html" title="Clusters">
 <link rel="prev" href="reordering-in-levels-0-and-1.html" title="Reordering in levels 0 and 1">
 <link rel="next" href="level-2.html" title="Level 2">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="p" href="reordering-in-levels-0-and-1.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="level-2.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
-<div class="sect1">
+<div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="the-distinction-between-levels-0-and-1"></a>The distinction between levels 0 and 1</h2></div></div></div>
 <p>
-    So, the above is pretty much what cluster levels 0 and 1 do. The
-    only difference between the two is this: in level 0, at the very
-    beginning of the shaping process, we also merge clusters between
-    base characters and all Unicode marks (combining or not) following
-    them. E.g.:
-  </p>
+      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.
+    </p>
+<p>
+      For example, let us start with the following character sequence
+      (top row) and accompanying initial cluster values (bottom row):
+    </p>
 <pre class="programlisting">
-  A,acute,B
-  0,1    ,2
-</pre>
+      A,acute,B
+      0,1    ,2
+    </pre>
 <p>
-    will become:
-  </p>
+      The <code class="literal">acute</code> is a Unicode mark. If HarfBuzz is
+      using cluster level 0 on this sequence, then the
+      <code class="literal">A</code> and <code class="literal">acute</code> clusters will
+      merge, and the result will become:
+    </p>
 <pre class="programlisting">
-  A,acute,B
-  0,0    ,2
-</pre>
+      A,acute,B
+      0,0    ,2
+    </pre>
+<p>
+      This merger is performed before any other script-shaping
+      steps.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      But this initial cluster-merging behavior makes it impossible
+      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.
+    </p>
 <p>
-    This is the default behavior. We do it because Windows did it and
-    old HarfBuzz did it, so this remained the default. But this behavior
-    makes it impossible to color diacritic marks differently from their
-    base characters. That's why in level 1 we do not perform this
-    initial merging step.
-  </p>
+      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. 
+    </p>
 <p>
-    For clients, level 0 is more convenient if they rely on HarfBuzz
-    clusters for cursor positioning. But that's wrong anyway: cursor
-    positions should be determined based on Unicode grapheme boundaries,
-    NOT shaping clusters. As such, level 1 clusters are preferred.
-  </p>
+      One final facet of levels 0 and 1 is worth noting. HarfBuzz
+      currently does not allow any
+      <span class="emphasis"><em>multiple-substitution</em></span> GSUB lookups to 
+      replace a glyph with zero glyphs (in other words, to delete a
+      glyph).
+    </p>
 <p>
-    One last note about levels 0 and 1. We currently don't allow a
-    <code class="literal">MultipleSubst</code> lookup to replace a glyph with zero
-    glyphs (i.e., to delete a glyph). But in some other situations,
-    glyphs can be deleted. In those cases, if the glyph being deleted is
-    the last glyph of its cluster, we make sure to merge the cluster
-    with a neighboring cluster.
-  </p>
+      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.
+    </p>
 <p>
-    This is, 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 currently relies on this
-    guarantee.
-  </p>
+      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.
+    </p>
 <p>
-    Incidentally, Apple's CoreText does something else 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.
-  </p>
+      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.
+    </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/unicode-character-categories.html b/docs/html/unicode-character-categories.html
new file mode 100644 (file)
index 0000000..2b97961
--- /dev/null
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Unicode character categories: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="shaping-concepts.html" title="Shaping concepts">
+<link rel="prev" href="shaping-operations.html" title="Shaping operations">
+<link rel="next" href="text-runs.html" title="Text runs">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="shaping-concepts.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="shaping-operations.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="text-runs.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="unicode-character-categories"></a>Unicode character categories</h2></div></div></div>
+<p>
+      Shaping models are typically specified with respect to how
+      scripts are defined in the Unicode standard.
+    </p>
+<p>
+      Every codepoint in the Unicode Character Database (UCD) is
+      assigned a <span class="emphasis"><em>Unicode General Category</em></span> (UGC),
+      which provides the most fundamental information about the
+      codepoint: whether the codepoint represents a
+      <span class="emphasis"><em>Letter</em></span>, a <span class="emphasis"><em>Mark</em></span>, a
+      <span class="emphasis"><em>Number</em></span>, <span class="emphasis"><em>Punctuation</em></span>, a
+      <span class="emphasis"><em>Symbol</em></span>, a <span class="emphasis"><em>Separator</em></span>,
+      or something else (<span class="emphasis"><em>Other</em></span>).
+    </p>
+<p>
+      These UGC properties are "Major" categories. Each codepoint is
+      further assigned to a "minor" category within its Major
+      category, such as "Letter, uppercase" (<code class="literal">Lu</code>) or
+      "Letter, modifier" (<code class="literal">Lm</code>).
+    </p>
+<p>
+      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
+      (<code class="literal">Mn</code>), spacing combining
+      (<code class="literal">Mc</code>), or enclosing (<code class="literal">Me</code>).
+    </p>
+<p>
+      In addition to the UGC property, codepoints in the Indic and
+      Southeast Asian scripts are also assigned
+      <span class="emphasis"><em>Unicode Indic Syllabic Category</em></span> (UISC) and
+      <span class="emphasis"><em>Unicode Indic Positional Category</em></span> (UIPC)
+      properties that provide more detailed information needed for
+      shaping.
+    </p>
+<p>
+      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).
+    </p>
+<p>
+      Some complex 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.
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index f404986..13e1a4f 100644 (file)
Binary files a/docs/html/up-insensitive.png and b/docs/html/up-insensitive.png differ
index 80b4b37..67a9054 100644 (file)
Binary files a/docs/html/up.png and b/docs/html/up.png differ
index 497e2e6..71cda2c 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="fonts-and-faces.html" title="Fonts and faces">
 <link rel="prev" href="fonts-and-faces.html" title="Fonts and faces">
 <link rel="next" href="using-your-own-font-functions.html" title="Using your own font functions">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 043956c..400e3e0 100644 (file)
@@ -7,8 +7,8 @@
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="fonts-and-faces.html" title="Fonts and faces">
 <link rel="prev" href="using-harfbuzzs-native-opentype-implementation.html" title="Using HarfBuzz's native OpenType implementation">
-<link rel="next" href="clusters.html" title="">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="clusters.html" title="Clusters">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
index 0f265ce..5b0ebed 100644 (file)
@@ -8,7 +8,7 @@
 <link rel="up" href="buffers-language-script-and-direction.html" title="Buffers, language, script and direction">
 <link rel="prev" href="setting-buffer-properties.html" title="Setting buffer properties">
 <link rel="next" href="customizing-unicode-functions.html" title="Customizing Unicode functions">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@@ -26,6 +26,6 @@
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/what-harfbuzz-doesnt-do.html b/docs/html/what-harfbuzz-doesnt-do.html
new file mode 100644 (file)
index 0000000..33309a1
--- /dev/null
@@ -0,0 +1,111 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>What HarfBuzz doesn't do: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
+<link rel="prev" href="ch01s03.html" title="What does HarfBuzz do?">
+<link rel="next" href="why-is-it-called-harfbuzz.html" title="Why is it called HarfBuzz?">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="what-is-harfbuzz.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch01s03.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="why-is-it-called-harfbuzz.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="what-harfbuzz-doesnt-do"></a>What HarfBuzz doesn't do</h2></div></div></div>
+<p>
+      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.
+    </p>
+<p>
+      It is important to note that if you are implementing a complete
+      text-layout engine you may have other responsibilities that
+      HarfBuzz will <span class="emphasis"><em>not</em></span> help you with. For example:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+<p>
+          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:
+        </p>
+<pre class="programlisting">
+         A B C [space] ג ב א [space] D E F
+        </pre>
+<p>
+          but will expect to see in the output:
+        </p>
+<pre class="programlisting">
+         ABC אבג DEF
+        </pre>
+<p>
+          This reordering is called <span class="emphasis"><em>bidi processing</em></span>
+          ("bidi" 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 <a class="ulink" href="http://icu-project.org/" target="_top">ICU</a> and <a class="ulink" href="http://fribidi.org/" target="_top">fribidi</a> can do this for you.
+        </p>
+</li>
+<li class="listitem">
+<p>
+          HarfBuzz won't help you with text that contains different font
+          properties. For instance, if you have the string "a
+          <span class="emphasis"><em>huge</em></span> breakfast", and you expect
+          "huge" to be italic, then you will need to send three
+          strings to HarfBuzz: <code class="literal">a</code>, in your Roman font;
+          <code class="literal">huge</code> using your italic font; and
+          <code class="literal">breakfast</code> using your Roman font again.
+       </p>
+<p>
+          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.
+        </p>
+</li>
+<li class="listitem">
+<p>
+          HarfBuzz won't help you with line breaking, hyphenation, or
+          justification. As mentioned above, HarfBuzz lays out the string
+          along a <span class="emphasis"><em>single line</em></span> 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.
+        </p>
+<p>
+          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.
+        </p>
+</li>
+</ul></div>
+<p>
+      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—what you then do with the glyphs that your font
+      returns is up to you. 
+    </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index aff2f7d..a3eb0a2 100644 (file)
@@ -7,8 +7,8 @@
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="pt01.html" title="Part I. User's manual">
 <link rel="prev" href="pt01.html" title="Part I. User's manual">
-<link rel="next" href="why-is-it-called-harfbuzz.html" title="Why is it called HarfBuzz?">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="next" href="why-do-i-need-a-shaping-engine.html" title="Why do I need a shaping engine?">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
 <td><a accesskey="p" href="pt01.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
-<td><a accesskey="n" href="why-is-it-called-harfbuzz.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+<td><a accesskey="n" href="why-do-i-need-a-shaping-engine.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="chapter">
 <div class="titlepage"><div><div><h2 class="title">
 <a name="what-is-harfbuzz"></a>What is HarfBuzz?</h2></div></div></div>
 <div class="toc"><dl class="toc">
-<dt><span class="section"><a href="what-is-harfbuzz.html#why-do-i-need-it">Why do I need it?</a></span></dt>
+<dt><span class="section"><a href="what-is-harfbuzz.html#what-is-text-shaping">What is text shaping?</a></span></dt>
+<dt><span class="section"><a href="why-do-i-need-a-shaping-engine.html">Why do I need a shaping engine?</a></span></dt>
+<dt><span class="section"><a href="ch01s03.html">What does HarfBuzz do?</a></span></dt>
+<dt><span class="section"><a href="what-harfbuzz-doesnt-do.html">What HarfBuzz doesn't do</a></span></dt>
 <dt><span class="section"><a href="why-is-it-called-harfbuzz.html">Why is it called HarfBuzz?</a></span></dt>
 </dl></div>
 <p>
-    HarfBuzz is a <span class="emphasis"><em>text shaping engine</em></span>. It solves
-    the problem of selecting and positioning glyphs from a font given a
-    Unicode string.
+    HarfBuzz is a <span class="emphasis"><em>text-shaping engine</em></span>. 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. 
+  </p>
+<p>
+    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.
   </p>
 <div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="why-do-i-need-it"></a>Why do I need it?</h2></div></div></div>
+<a name="what-is-text-shaping"></a>What is text shaping?</h2></div></div></div>
+<p>
+      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.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      Modern software systems generally only deal with strings in the
+      Unicode encoding scheme (although legacy systems and documents may
+      involve other encodings).
+    </p>
+<p>
+      There are several font formats that a program might
+      encounter, each of which has a set of standard text-shaping
+      rules.
+    </p>
+<p>The dominant format is <a class="ulink" href="http://www.microsoft.com/typography/otspec/" target="_top">OpenType</a>. The
+    OpenType specification defines a series of <a class="ulink" href="https://github.com/n8willis/opentype-shaping-documents" target="_top">shaping models</a> for
+    various scripts from around the world. These shaping models depend on
+    the font incorporating certain features as
+    <span class="emphasis"><em>lookups</em></span> in its <code class="literal">GSUB</code> 
+    and <code class="literal">GPOS</code> tables.
+    </p>
 <p>
-      Text shaping is an integral part of preparing text for display. It
-      is a fairly low level operation; HarfBuzz is used directly by
-      graphic rendering libraries such as Pango, and the layout engines
-      in Firefox, LibreOffice and Chromium. Unless you are
-      <span class="emphasis"><em>writing</em></span> one of these layout engines yourself,
-      you will probably not need to use HarfBuzz - normally higher level
-      libraries will turn text into glyphs for you.
+      Alternatively, OpenType fonts can include shaping features for
+      the <a class="ulink" href="https://graphite.sil.org/" target="_top">Graphite</a> shaping model.
     </p>
 <p>
-      However, if you <span class="emphasis"><em>are</em></span> writing a layout engine
-      or graphics library yourself, you will need to perform text
-      shaping, and this is where HarfBuzz can help you. Here are some
-      reasons why you need it:
+      TrueType fonts can also include OpenType shaping
+      features. Alternatively, TrueType fonts can also include <a class="ulink" href="https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html" target="_top">Apple
+      Advanced Typography</a> (AAT) tables to implement shaping
+      support. AAT fonts are generally only found on macOS and iOS systems.
     </p>
-<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
-<li class="listitem"><p>
-          OpenType fonts contain a set of glyphs, indexed by glyph ID.
-          The glyph ID within the font does not necessarily relate to a
-          Unicode codepoint. For instance, some fonts have the letter
-          "a" as glyph ID 1. To pull the right glyph out of
-          the font in order to display it, you need to consult a table
-          within the font (the "cmap" table) which maps
-          Unicode codepoints to glyph IDs. Text shaping turns codepoints
-          into glyph IDs.
-        </p></li>
-<li class="listitem"><p>
-          Many OpenType fonts contain ligatures: combinations of
-          characters which are rendered together. For instance, it's
-          common for the <code class="literal">fi</code> combination to appear in
-          print as the single ligature "fi". Whether you should
-          render text as <code class="literal">fi</code> or "fi" does not
-          depend on the input text, but on the capabilities of the font
-          and the level of ligature application you wish to perform.
-          Text shaping involves querying the font's ligature tables and
-          determining what substitutions should be made.
-        </p></li>
-<li class="listitem"><p>
-          While ligatures like "fi" are typographic
-          refinements, some languages <span class="emphasis"><em>require</em></span> such
-          substitutions to be made in order to display text correctly.
-          In Tamil, when the letter "TTA" (ட) letter is
-          followed by "U" (உ), the combination should appear
-          as the single glyph "டு". The sequence of Unicode
-          characters "டஉ" needs to be rendered as a single
-          glyph from the font - text shaping chooses the correct glyph
-          from the sequence of characters provided.
-        </p></li>
-<li class="listitem"><p>
-          Similarly, each Arabic character has four different variants:
-          within a font, there will be glyphs for the initial, medial,
-          final, and isolated forms of each letter. Unicode only encodes
-          one codepoint per character, and so a Unicode string will not
-          tell you which glyph to use. Text shaping chooses the correct
-          form of the letter and returns the correct glyph from the font
-          that you need to render.
-        </p></li>
-<li class="listitem"><p>
-          Other languages have marks and accents which need to be
-          rendered in certain positions around a base character. For
-          instance, the Moldovan language has the Cyrillic letter
-          "zhe" (ж) with a breve accent, like so: ӂ. Some
-          fonts will contain this character as an individual glyph,
-          whereas other fonts will not contain a zhe-with-breve glyph
-          but expect the rendering engine to form the character by
-          overlaying the two glyphs ж and ˘. Where you should draw the
-          combining breve depends on the height of the preceding glyph.
-          Again, for Arabic, the correct positioning of vowel marks
-          depends on the height of the character on which you are
-          placing the mark. 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, and if so, where to
-          position those marks.
-        </p></li>
-</ul></div>
 <p>
-      If this is something that you need to do, then you need a text
-      shaping engine: you could use Uniscribe if you are using Windows;
-      you could use CoreText on OS X; or you could use HarfBuzz. In the
-      rest of this manual, we are going to assume that you are the
-      implementor of a text layout engine.
+      Text strings will usually be tagged with a script and language
+      tag that provide the context needed to perform text shaping
+      correctly.  The necessary <a class="ulink" href="https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags" target="_top">script</a> 
+      and <a class="ulink" href="https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags" target="_top">language</a>
+      tags are defined by OpenType.
     </p>
 </div>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/why-do-i-need-a-shaping-engine.html b/docs/html/why-do-i-need-a-shaping-engine.html
new file mode 100644 (file)
index 0000000..1c2350b
--- /dev/null
@@ -0,0 +1,174 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Why do I need a shaping engine?: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
+<link rel="prev" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
+<link rel="next" href="ch01s03.html" title="What does HarfBuzz do?">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="what-is-harfbuzz.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="what-is-harfbuzz.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch01s03.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="why-do-i-need-a-shaping-engine"></a>Why do I need a shaping engine?</h2></div></div></div>
+<p>
+      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.
+    </p>
+<p>
+      Text shaping is a fairly low-level operation. HarfBuzz is
+      used directly by text-handling libraries like <a class="ulink" href="https://www.pango.org/" target="_top">Pango</a>, as well as by the layout
+      engines in Firefox, LibreOffice, and Chromium. Unless you are
+      <span class="emphasis"><em>writing</em></span> 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.
+    </p>
+<p>
+      However, if you <span class="emphasis"><em>are</em></span> writing a layout engine
+      or graphics library yourself, then you will need to perform text
+      shaping, and this is where HarfBuzz can help you.
+    </p>
+<p>
+      Here are some specific scenarios where a text-shaping engine
+      like HarfBuzz helps you:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+<p>
+          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 <code class="literal">glyph ID</code>.
+       </p>
+<p>
+          A particular glyph ID within the font does not necessarily
+         correlate to a predictable Unicode codepoint. For instance,
+         some fonts have the letter "a" as glyph ID 1, but
+         many others do not. In order to retrieve the right glyph
+         from the font to display "a", you need to consult
+         the table inside the font (the <code class="literal">cmap</code>
+         table) that maps Unicode codepoints to glyph IDs. In other
+         words, <span class="emphasis"><em>text shaping turns codepoints into glyph
+         IDs</em></span>.
+        </p>
+</li>
+<li class="listitem">
+<p>
+          Many OpenType fonts contain ligatures: combinations of
+          characters that are rendered as a single unit. For instance,
+         it is common for the "f, i" letter
+         sequence to appear in print as the single ligature glyph
+         "fi".
+       </p>
+<p>
+         Whether you should render an "f, i" sequence
+         as <code class="literal">fi</code> or as "fi" does not
+          depend on the input text. Instead, it depends on the whether
+         or not the font includes an "fi" 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, <span class="emphasis"><em>text shaping involves
+         querying the font's ligature tables and determining what
+         substitutions should be made</em></span>. 
+        </p>
+</li>
+<li class="listitem">
+<p>
+          While ligatures like "fi" are optional typographic
+          refinements, some languages <span class="emphasis"><em>require</em></span> certain
+          substitutions to be made in order to display text correctly.
+        </p>
+<p>
+         For example, in Tamil, when the letter "TTA" (ட)
+         letter is followed by "U" (உ), the pair
+         must be replaced by the single glyph "டு". The
+         sequence of Unicode characters "டஉ" needs to be
+         substituted with a single "டு" glyph from the
+         font.
+       </p>
+<p>
+         But "டு" does not have a Unicode codepoint. To
+         find this glyph, you need to consult the table inside 
+         the font (the <code class="literal">GSUB</code> table) that contains
+         substitution information. In other words, <span class="emphasis"><em>text shaping 
+         chooses the correct glyph for a sequence of characters
+         provided</em></span>.
+        </p>
+</li>
+<li class="listitem">
+<p>
+          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.
+       </p>
+<p>
+         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, <span class="emphasis"><em>text
+         shaping chooses the correct form of the letter by its
+         position and returns the correct glyph from the font</em></span>.
+        </p>
+</li>
+<li class="listitem">
+<p>
+          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
+          "zhe" (ж) with a breve accent, like so: "ӂ".
+       </p>
+<p>
+         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 "ж" and "˘"
+         glyphs.
+       </p>
+<p>
+         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 <code class="literal">GPOS</code> table) that contains
+         positioning information.
+          In other words, <span class="emphasis"><em>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—and,
+         if so, where to position those marks.</em></span>
+        </p>
+</li>
+</ul></div>
+<p>
+      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.
+    </p>
+<div class="note"><p>
+       In the rest of this manual, the text will assume that the reader
+       is that implementor of a text-layout engine.
+      </p></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 960d835..dbc62c1 100644 (file)
@@ -6,9 +6,9 @@
 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
 <link rel="home" href="index.html" title="HarfBuzz Manual">
 <link rel="up" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
-<link rel="prev" href="what-is-harfbuzz.html" title="What is HarfBuzz?">
-<link rel="next" href="install-harfbuzz.html" title="Install HarfBuzz">
-<meta name="generator" content="GTK-Doc V1.27.1 (XML mode)">
+<link rel="prev" href="what-harfbuzz-doesnt-do.html" title="What HarfBuzz doesn't do">
+<link rel="next" href="install-harfbuzz.html" title="Installing HarfBuzz">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
 <link rel="stylesheet" href="style.css" type="text/css">
 </head>
 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 <td width="100%" align="left" class="shortcuts"></td>
 <td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
 <td><a accesskey="u" href="what-is-harfbuzz.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
-<td><a accesskey="p" href="what-is-harfbuzz.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="p" href="what-harfbuzz-doesnt-do.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
 <td><a accesskey="n" href="install-harfbuzz.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
 </tr></table>
 <div class="section">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
 <a name="why-is-it-called-harfbuzz"></a>Why is it called HarfBuzz?</h2></div></div></div>
 <p>
-      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
-      abstracted out to its own project. This project is maintained by
-      Behdad Esfahbod, and named HarfBuzz. Originally, it was a shaping
-      engine for OpenType fonts - "HarfBuzz" is the Persian
-      for "open type".
+      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—"HarfBuzz" is
+      the Persian for "open type".
     </p>
 </div>
 <div class="footer">
-<hr>Generated by GTK-Doc V1.27.1</div>
+<hr>Generated by GTK-Doc V1.25</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/working-with-harfbuzz-clusters.html b/docs/html/working-with-harfbuzz-clusters.html
new file mode 100644 (file)
index 0000000..8d40cd0
--- /dev/null
@@ -0,0 +1,227 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Working with HarfBuzz clusters: HarfBuzz Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
+<link rel="home" href="index.html" title="HarfBuzz Manual">
+<link rel="up" href="clusters.html" title="Clusters">
+<link rel="prev" href="clusters.html" title="Clusters">
+<link rel="next" href="a-clustering-example-for-levels-0-and-1.html" title="A clustering example for levels 0 and 1">
+<meta name="generator" content="GTK-Doc V1.25 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="clusters.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="clusters.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="a-clustering-example-for-levels-0-and-1.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="section">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="working-with-harfbuzz-clusters"></a>Working with HarfBuzz clusters</h2></div></div></div>
+<p>
+      When you add text to a HarfBuzz buffer, each code point must be
+      assigned a <span class="emphasis"><em>cluster value</em></span>.
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      Some of the shaping operations performed by HarfBuzz —
+      such as reordering, composition, decomposition, and substitution
+      — 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.
+    </p>
+<p>
+      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).
+    </p>
+<p>
+      For example, if the initial sequence of cluster values was:
+    </p>
+<pre class="programlisting">
+      0,1,2,3,4
+    </pre>
+<p>
+      and the final sequence of cluster values is:
+    </p>
+<pre class="programlisting">
+      0,0,3,3
+    </pre>
+<p>
+      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).
+    </p>
+<p>
+      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.
+    </p>
+<p>
+      For left-to-right scripts (LTR) and top-to-bottom scripts (TTB),
+      HarfBuzz will preserve the monotonic property: client programs
+      are guaranteed that monotonically increasing initial clulster
+      values will be returned as monotonically increasing final
+      cluster values.
+    </p>
+<p>
+      For right-to-left scripts (RTL) and bottom-to-top scripts (BTT),
+      the directionality of the buffer itself is reversed for final
+      output as a matter of design. Therefore, HarfBuzz inverts the
+      monotonic property: client programs are guaranteed that
+      monotonically increasing initial clulster values will be
+      returned as monotonically <span class="emphasis"><em>decreasing</em></span> final
+      cluster values.
+    </p>
+<p>
+      Client programs can adjust how HarfBuzz handles clusters during
+      shaping by setting the
+      <code class="literal">cluster_level</code> of the
+      buffer. HarfBuzz offers three <span class="emphasis"><em>levels</em></span> of
+      clustering support for this property:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+<p><span class="emphasis"><em>Level 0</em></span> is the default and
+       reproduces the behavior of the old HarfBuzz library.
+       </p>
+<p>
+         The distinguishing feature of level 0 behavior is that, at
+         the beginning of processing the buffer, all code points that
+         are categorized as <span class="emphasis"><em>marks</em></span>,
+         <span class="emphasis"><em>modifier symbols</em></span>, or
+         <span class="emphasis"><em>Emoji extended pictographic</em></span> modifiers,
+         as well as the <span class="emphasis"><em>Zero Width Joiner</em></span> and
+         <span class="emphasis"><em>Zero Width Non-Joiner</em></span> code points, are
+         assigned the cluster value of the closest preceding code
+         point from <span class="emphasis"><em>different</em></span> category. 
+       </p>
+<p>
+         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 <a class="ulink" href="https://www.unicode.org/reports/tr29/#Regex_Definitions" target="_top">Unicode
+         Technical Report 29</a>.
+       </p>
+<p>
+         Client programs can specify level 0 behavior for a buffer by
+         setting its <code class="literal">cluster_level</code> to
+         <code class="literal">HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES</code>. 
+       </p>
+</li>
+<li class="listitem">
+<p>
+         <span class="emphasis"><em>Level 1</em></span> 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.
+       </p>
+<p>
+         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).
+       </p>
+<p>
+         Client programs can specify level 1 behavior for a buffer by
+         setting its <code class="literal">cluster_level</code> to
+         <code class="literal">HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS</code>. 
+       </p>
+</li>
+<li class="listitem">
+<p>
+         <span class="emphasis"><em>Level 2</em></span> differs significantly in how it
+         treats cluster values. In level 2, HarfBuzz never merges
+         clusters.
+       </p>
+<p>
+         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.
+       </p>
+<p>
+         Client programs can specify level 2 behavior for a buffer by
+         setting its <code class="literal">cluster_level</code> to
+         <code class="literal">HB_BUFFER_CLUSTER_LEVEL_CHARACTERS</code>. 
+       </p>
+</li>
+</ul></div>
+<p>
+      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). 
+    </p>
+<p>
+      It is not <span class="emphasis"><em>required</em></span> 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.
+    </p>
+<p>
+      In levels 0 and 1, HarfBuzz implements the following conceptual
+      model for cluster values:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc; ">
+<li class="listitem"><p>
+          If the sequence of input cluster values is monotonic, the
+         sequence of cluster values will remain monotonic.
+       </p></li>
+<li class="listitem"><p>
+          Each cluster value represents a single cluster.
+       </p></li>
+<li class="listitem"><p>
+          Each cluster contains one or more glyphs and one or more
+          characters.
+       </p></li>
+</ul></div>
+<p>
+      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:
+    </p>
+<div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc; ">
+<li class="listitem"><p>
+         All adjacent glyphs having the same final cluster
+         value belong to the same cluster.
+       </p></li>
+<li class="listitem"><p>
+          Each character belongs to the cluster that has the highest
+         cluster value <span class="emphasis"><em>not larger than</em></span> its
+         initial cluster value.
+       </p></li>
+</ul></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.25</div>
+</body>
+</html>
\ No newline at end of file
index 9eddb71..1c6b5da 100644 (file)
@@ -1,3 +1,9 @@
+<?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>
   <section id="creating-and-destroying-buffers">
     <title>Creating and destroying buffers</title>
     <para>
-      As we saw in our initial example, a buffer is created and
+      As we saw in our <emphasis>Getting Started</emphasis> example, a
+      buffer is created and 
       initialized with <literal>hb_buffer_create()</literal>. 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 that it creates (such as
-      buffers), so you don't have to. When you have finished working on
+      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 <literal>hb_buffer_destroy()</literal>:
     </para>
     <programlisting language="C">
@@ -74,4 +81,4 @@ void somefunc(hb_buffer_t *buffer) {
     <para>
     </para>
   </section>
-</chapter>
\ No newline at end of file
+</chapter>
index 608371b..228cc56 100644 (file)
+<?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">
-<sect1 id="clusters">
   <title>Clusters</title>
-  <para>
-    In shaping text, a <emphasis>cluster</emphasis> is a sequence of
-    code points that needs to be treated as a single, indivisible unit.
-  </para>
-  <para>
-    When you add text to a HB buffer, each character is associated with
-    a <emphasis>cluster value</emphasis>. This is an arbitrary number as
-    far as HB is concerned.
-  </para>
-  <para>
-    Most clients will use UTF-8, UTF-16, or UTF-32 indices, but the
-    actual number does not matter. Moreover, it is not required for the
-    cluster values to be monotonically increasing, but pretty much all
-    of HB's tests are performed on monotonically increasing cluster
-    numbers. Nevertheless, there is no such assumption in the code
-    itself. With that in mind, let's examine what happens with cluster
-    values during shaping under each cluster-level.
-  </para>
-  <para>
-    HarfBuzz provides three <emphasis>levels</emphasis> of clustering
-    support. Level 0 is the default behavior and reproduces the behavior
-    of the old HarfBuzz library. Level 1 tweaks this behavior slightly
-    to produce better results, so level 1 clustering is recommended for
-    code that is not required to implement backward compatibility with
-    the old HarfBuzz.
-  </para>
-  <para>
-    Level 2 differs significantly in how it treats cluster values.
-    Levels 0 and 1 both process ligatures and glyph decomposition by
-    merging clusters; level 2 does not.
-  </para>
-  <para>
-    The conceptual model for what the cluster values mean, in levels 0
-    and 1, is this:
-  </para>
-  <itemizedlist spacing="compact">
-    <listitem>
-      <para>
-        the sequence of cluster values will always remain monotone
-      </para>
-    </listitem>
-    <listitem>
-      <para>
-        each 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>
-    Assuming that initial cluster numbers were monotonically increasing
-    and distinct, then all adjacent glyphs having the same cluster
-    number belong to the same cluster, and all characters belong to the
-    cluster that has the highest number not larger than their initial
-    cluster number. This will become clearer with an example.
-  </para>
-</sect1>
-<sect1 id="a-clustering-example-for-levels-0-and-1">
-  <title>A clustering example for levels 0 and 1</title>
-  <para>
-    Let's say we start with the following character sequence and cluster
-    values:
-  </para>
-  <programlisting>
-   A,B,C,D,E
-   0,1,2,3,4
-</programlisting>
-  <para>
-    We then map the characters to glyphs. For simplicity, let's 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>
-    ligate, then the clusters to which they belong &quot;merge&quot;.
-    This merged cluster takes for its cluster number the minimum of all
-    the cluster numbers of the clusters that went in. In this case, we
-    get:
-  </para>
-  <programlisting>
-   A,BC,D,E
-   0,1 ,3,4
-</programlisting>
-  <para>
-    Now let's assume that the <literal>BC</literal> glyph decomposes
-    into three components, and <literal>D</literal> also decomposes into
-    two. The 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>
-    Now if <literal>BC2</literal> and <literal>D0</literal> ligate, then
-    their clusters (numbers 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>
-    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>
-</sect1>
-<sect1 id="reordering-in-levels-0-and-1">
-  <title>Reordering in levels 0 and 1</title>
-  <para>
-    Another common operation in the more complex shapers is when things
-    reorder. In those cases, to maintain monotone clusters, HB merges
-    the clusters of everything in the reordering sequence. For example,
-    let's again start with the character sequence:
-  </para>
-  <programlisting>
-   A,B,C,D,E
-   0,1,2,3,4
-</programlisting>
-  <para>
-    If <literal>D</literal> is reordered before <literal>B</literal>,
-    then the <literal>B</literal>, <literal>C</literal>, and
-    <literal>D</literal> clusters merge, and we get:
-  </para>
-  <programlisting>
-   A,D,B,C,E
-   0,1,1,1,4
-</programlisting>
-  <para>
-    This is clearly not ideal, but it is the only sensible way to
-    maintain monotone indices and retain the true relationship between
-    glyphs and characters.
-  </para>
-</sect1>
-<sect1 id="the-distinction-between-levels-0-and-1">
-  <title>The distinction between levels 0 and 1</title>
-  <para>
-    So, the above is pretty much what cluster levels 0 and 1 do. The
-    only difference between the two is this: in level 0, at the very
-    beginning of the shaping process, we also merge clusters between
-    base characters and all Unicode marks (combining or not) following
-    them. E.g.:
-  </para>
-  <programlisting>
-  A,acute,B
-  0,1    ,2
-</programlisting>
-  <para>
-    will become:
-  </para>
-  <programlisting>
-  A,acute,B
-  0,0    ,2
-</programlisting>
-  <para>
-    This is the default behavior. We do it because Windows did it and
-    old HarfBuzz did it, so this remained the default. But this behavior
-    makes it impossible to color diacritic marks differently from their
-    base characters. That's why in level 1 we do not perform this
-    initial merging step.
-  </para>
-  <para>
-    For clients, level 0 is more convenient if they rely on HarfBuzz
-    clusters for cursor positioning. But that's wrong anyway: cursor
-    positions should be determined based on Unicode grapheme boundaries,
-    NOT shaping clusters. As such, level 1 clusters are preferred.
-  </para>
-  <para>
-    One last note about levels 0 and 1. We currently don't allow a
-    <literal>MultipleSubst</literal> lookup to replace a glyph with zero
-    glyphs (i.e., to delete a glyph). But in some other situations,
-    glyphs can be deleted. In those cases, if the glyph being deleted is
-    the last glyph of its cluster, we make sure to merge the cluster
-    with a neighboring cluster.
-  </para>
-  <para>
-    This is, 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 currently relies on this
-    guarantee.
-  </para>
-  <para>
-    Incidentally, Apple's CoreText does something else 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>
-</sect1>
-<sect1 id="level-2">
-  <title>Level 2</title>
-  <para>
-    Level 2 is a different beast from levels 0 and 1. It is simple to
-    describe, but hard to make sense of. It simply doesn't do any
-    cluster merging whatsoever. When things ligate or otherwise multiple
-    glyphs turn into one, the cluster value of the first glyph is
-    retained.
-  </para>
-  <para>
-    Here are a few examples of why processing cluster values produced at
-    this level might be tricky:
-  </para>
-  <sect2 id="ligatures-with-combining-marks">
-    <title>Ligatures with combining marks</title>
-    <para>
-      Imagine capital letters are bases and lower case letters are
-      combining marks. With an input sequence like this:
+  <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>
-  A,a,B,b,C,c
-  0,1,2,3,4,5
-</programlisting>
+      0,0,3,3
+    </programlisting>
     <para>
-      if <literal>A,B,C</literal> ligate, then here are the cluster
-      values one would get under the various levels:
+      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>
-      level 0:
+      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 left-to-right scripts (LTR) and top-to-bottom scripts (TTB),
+      HarfBuzz will preserve the monotonic property: client programs
+      are guaranteed that monotonically increasing initial clulster
+      values will be returned as monotonically increasing final
+      cluster values.
+    </para>
+    <para>
+      For right-to-left scripts (RTL) and bottom-to-top scripts (BTT),
+      the directionality of the buffer itself is reversed for final
+      output as a matter of design. Therefore, HarfBuzz inverts the
+      monotonic property: client programs are guaranteed that
+      monotonically increasing initial clulster values will be
+      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>
-  ABC,a,b,c
-  0  ,0,0,0
-</programlisting>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
     <para>
-      level 1:
+      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>
-  ABC,a,b,c
-  0  ,0,0,5
-</programlisting>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
     <para>
-      level 2:
+      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>
-  ABC,a,b,c
-  0  ,1,3,5
-</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>
-      Making sense of the last example is the hardest for a client,
-      because there is nothing in the cluster values to suggest that
-      <literal>B</literal> and <literal>C</literal> ligated with
-      <literal>A</literal>.
+      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>
-  </sect2>
-  <sect2 id="reordering">
-    <title>Reordering</title>
+  </section>
+  <section id="reordering-in-levels-0-and-1">
+    <title>Reordering in levels 0 and 1</title>
     <para>
-      Another tricky case is when things reorder. Under level 2:
+      Another common operation in the more complex 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>
+      A,B,C,D,E
+      0,1,2,3,4
+    </programlisting>
     <para>
-      Now imagine <literal>D</literal> moves before
-      <literal>B</literal>:
+      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,3,1,2,4
-</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>
-      Now, if <literal>D</literal> ligates with <literal>B</literal>, we
-      get:
+      For example, let us start with the following character sequence
+      (top row) and accompanying initial cluster values (bottom row):
     </para>
     <programlisting>
-  A,DB,C,E
-  0,3 ,2,4
-</programlisting>
+      A,acute,B
+      0,1    ,2
+    </programlisting>
     <para>
-      In a different scenario, <literal>A</literal> and
-      <literal>B</literal> could have ligated
-      <emphasis>before</emphasis> <literal>D</literal> reordered; that
-      would have resulted in:
+      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>
-  AB,D,C,E
-  0 ,3,2,4   
-</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
+      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>
-      There's no way to differentiate between these two scenarios based
-      on the cluster numbers alone.
+      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>
-      Another problem happens with ligatures under level 2 if the
-      direction of the text is forced to opposite of its natural
-      direction (e.g. left-to-right Arabic). But that's too much of a
-      corner case to worry about.
+      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>
-  </sect2>
-</sect1>
+    <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
+       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>
index 7de0f05..5536004 100644 (file)
@@ -1,3 +1,9 @@
+<?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 and faces</title>
   <section id="using-freetype">
@@ -15,4 +21,4 @@
     <para>
     </para>
   </section>
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/docs/usermanual-getting-started.xml b/docs/usermanual-getting-started.xml
new file mode 100644 (file)
index 0000000..cc867e0
--- /dev/null
@@ -0,0 +1,307 @@
+<?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>
+    <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 provide 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>
+    <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
+             non-complex scripts. 
+           </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>
+    <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>
+          Guess 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, using FreeType for now.
+       </para>
+      </listitem>
+    </orderedlist>
+    <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>
+    <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">
+      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">
+      for (i = 0; i &lt; glyph_count; ++i) {
+      glyphid = glyph_info[i].codepoint;
+      x_offset = glyph_pos[i].x_offset / 64.0;
+      y_offset = glyph_pos[i].y_offset / 64.0;
+      x_advance = glyph_pos[i].x_advance / 64.0;
+      y_advance = glyph_pos[i].y_advance / 64.0;
+      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(hb_ft_font);
+    </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>
index ca674c0..78f06c7 100644 (file)
@@ -1,3 +1,9 @@
+<?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">
@@ -5,4 +11,4 @@
     <para>
     </para>
   </sect2>
-</sect1>
\ No newline at end of file
+</sect1>
diff --git a/docs/usermanual-hello-harfbuzz.xml b/docs/usermanual-hello-harfbuzz.xml
deleted file mode 100644 (file)
index 716b2f2..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-<chapter id="hello-harfbuzz">
-  <title>Hello, HarfBuzz</title>
-  <para>
-    Here's the simplest HarfBuzz that can possibly work. We will improve
-    it later.
-  </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, strlen(text), 0, strlen(text));
-</programlisting>
-  <orderedlist numeration="arabic">
-    <listitem override="2">
-      <para>
-        Guess the script, language and direction of the buffer.
-      </para>
-    </listitem>
-  </orderedlist>
-  <programlisting language="C">
-  hb_buffer_guess_segment_properties(buf);
-</programlisting>
-  <orderedlist numeration="arabic">
-    <listitem override="3">
-      <para>
-        Create a face and a font, using FreeType for now.
-      </para>
-    </listitem>
-  </orderedlist>
-  <programlisting language="C">
-  #include &lt;hb-ft.h&gt;
-  FT_New_Face(ft_library, font_path, index, &amp;face)
-  hb_font_t *font = hb_ft_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">
-  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">
-  for (i = 0; i &lt; glyph_count; ++i) {
-    glyphid = glyph_info[i].codepoint;
-    x_offset = glyph_pos[i].x_offset / 64.0;
-    y_offset = glyph_pos[i].y_offset / 64.0;
-    x_advance = glyph_pos[i].x_advance / 64.0;
-    y_advance = glyph_pos[i].y_advance / 64.0;
-    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(hb_ft_font);
-</programlisting>
-  <section id="what-harfbuzz-doesnt-do">
-    <title>What HarfBuzz doesn't do</title>
-    <para>
-      The code above will take a UTF8 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>
-      If you are implementing a text layout engine you may have other
-      responsibilities, that HarfBuzz will not help you with:
-    </para>
-    <itemizedlist>
-      <listitem>
-        <para>
-          HarfBuzz won't help you with bidirectionality. If you want to
-          lay out text with mixed Hebrew and English, you will need to
-          ensure that the buffer provided to HarfBuzz has those
-          characters in the correct layout order. This will be different
-          from the logical order in which the Unicode text is stored. 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 reorder a string from logical order into presentation order.
-          Before sending your string to HarfBuzz, you may need to apply the
-          bidi algorithm to it. Libraries such as ICU and fribidi 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, 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.
-          Similarly if you change font, font size, script, language or
-          direction within your string, you will need to shape each run
-          independently and then output them independently. HarfBuzz
-          expects to shape a run of characters sharing the same
-          properties.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
-          HarfBuzz won't help you with line breaking, hyphenation or
-          justification. As mentioned above, it 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. If you
-          want to layout text in paragraphs, you will probably want to send
-          each word of your text to HarfBuzz to determine its shaped width
-          after glyph substitutions, then work out how many words will fit
-          on a line, and then finally output each word of the line separated
-          by a space of the correct size to fully justify the paragraph.
-        </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 - what you then do with the glyphs that your font
-      returns is up to you. The example we saw above enough to get us
-      started using HarfBuzz. Now we are going to use the remainder of
-      HarfBuzz's API to refine that example and improve our text shaping
-      capabilities.
-    </para>
-  </section>
-</chapter>
\ No newline at end of file
index 899cc5b..a885d00 100644 (file)
+<?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>Install HarfBuzz</title>
+  <title>Installing HarfBuzz</title>
+  
   <section id="download">
-    <title id="download.title">Download</title>
+    <title id="download.title">Downloading HarfBuzz</title>
     <para>
-      For tarball releases of HarfBuzz, look
-      <ulink url="http://www.freedesktop.org/software/harfbuzz/release/">here</ulink>.
-      At the same place you will
-      also find Win32 binary bundles that include libharfbuzz DLL, hb-view.exe,
-      hb-shape.exe, and all dependencies.
+      The HarfBuzz source code is hosted at <ulink
+      url="https://github.com/harfbuzz/harfbuzz">github.com/harfbuzz/harfbuzz</ulink>. The
+      same source tree is also available at the
+      <ulink
+         url="http://cgit.freedesktop.org/harfbuzz/">Freedesktop.org</ulink>
+      site.
     </para>
     <para>
-      The canonical source tree is available
-      <ulink url="http://cgit.freedesktop.org/harfbuzz/">here</ulink>.
-      Also available on <ulink url="https://github.com/harfbuzz/harfbuzz">github</ulink>.
+      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">github.com/harfbuzz/harfbuzz/releases</ulink>
+      or from 
+      <ulink url="http://www.freedesktop.org/software/harfbuzz/release/">Freedesktop.org</ulink>.
     </para>
     <para>
-      The API that comes with <filename class='headerfile'>hb.h</filename> will
-      not change incompatibly. Other, peripheral, headers are more likely to go
-      through minor modifications, but again, will do our best to never change
-      API in an incompatible way. We will never break the ABI.
+      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 the <ulink
+      url="http://freedesktop.org/mailman/listinfo/harfbuzz/">HarfBuzz
+      mailing list</ulink>.
     </para>
     <para>
-      If you are not sure whether Pango or HarfBuzz is right for you, read
-      <ulink url="http://mces.blogspot.in/2009/11/pango-vs-harfbuzz.html">this</ulink>.
+      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</title>
+    <title>Building HarfBuzz</title>
+
+    <section id="building.linux">
+      <title>Building on Linux</title>
     <para>
-      On Linux, install the development packages for FreeType, Cairo, and GLib.
-      For example, on Ubuntu / Debian, you would do:
-      <programlisting>
-<command>sudo apt-get install</command> <package>gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev</package>
-      </programlisting>
-      whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
+      <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 yum install</command> <package>gcc gcc-c++ freetype-devel glib2-devel cairo-devel</package>
+       <command>sudo apt install</command> <package>gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev</package>
       </programlisting>
-      or using MacPorts:
+      On Fedora, RHEL, CentOS, or other Red-Hat&ndash;based systems, you would run:
       <programlisting>
-<command>sudo port install</command> <package>freetype glib2 cairo</package>
+       <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>./configure</command> followed by
+      <command>make</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>
-      If you are using a tarball, you can now proceed to running
-      <command>configure</command> and <command>make</command> as with any
-      other standard package. That should leave you with a shared library in
-      <filename>src/</filename>, and a few utility programs including hb-view
-      and hb-shape under <filename>util/</filename>.
+      <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> and
+      <ulink url="http://www.complang.org/ragel/">ragel</ulink>.
     </para>
     <para>
-      If you are bootstrapping from git, you need a few more tools before you
-      can run <filename>autogen.sh</filename> for the first time. Namely,
-      pkg-config and <ulink url="http://www.complang.org/ragel/">ragel</ulink>.
-      Again, on Ubuntu / Debian:
+      On Ubuntu or Debian, run:
       <programlisting>
-<command>sudo apt-get install</command> <package>autoconf automake libtool pkg-config ragel gtk-doc-tools</package>
+       <command>sudo apt-get install</command> <package>autoconf automake libtool pkg-config ragel gtk-doc-tools</package>
       </programlisting>
-      and on Fedora, RHEL, CentOS:
+      On Fedora, RHEL, CentOS, run:
       <programlisting>
-<command>sudo yum install</command> <package>autoconf automake libtool pkgconfig ragel gtk-doc</package>
+       <command>sudo yum install</command> <package>autoconf automake libtool pkgconfig ragel gtk-doc</package>
       </programlisting>
-      or using MacPorts:
+      
+    </para>
+    <para>
+      With <package>pkg-config</package> and <package>ragel</package>
+      installed, you can now run <command>./autogen.sh</command>,
+      followed by <command>./configure</command> and
+      <command>make</command> to build HarfBuzz.
+    </para>
+    </section>
+
+    
+    <section id="building.windows">
+      <title>Building on Windows</title>
+
+      <para>
+       On Windows, consider using Microsoft's free <ulink
+       url="https://github.com/Microsoft/vcpkg">vcpkg</ulink> utility
+       to build HarfBuzz, its dependencies, and other open-source
+       libraries. 
+      </para>
+      <para>
+       If you need to build HarfBuzz from source, first put the
+       <package>ragel</package> binary on your
+       <literal>PATH</literal>, then follow the appveyor CI cmake
+       <ulink
+           url="https://github.com/harfbuzz/harfbuzz/blob/master/appveyor.yml">build
+       instructions</ulink>. 
+      </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>autoconf automake libtool pkgconfig ragel gtk-doc</package>
+       <command>sudo port install</command> <package>freetype glib2 cairo</package>
       </programlisting>
-    </para>
+      </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>./configure</command>
+       </programlisting>
+       followed by:
+       <programlisting>        
+         <command>make</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>autoconf automake libtool pkgconfig ragel 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>autoconf automake libtool pkgconfig ragel gtk-doc</package>
+       </programlisting>
+       Finally, you can run:
+       <programlisting>
+         <command>./autogen.sh</command>
+       </programlisting>
+      </para>
+      <para>
+       <emphasis>(3)</emphasis> You can now build HarfBuzz (on either
+       a MacPorts or a Homebrew system) by running:
+       <programlisting>
+         <command>./configure</command>
+       </programlisting>
+       followed by:
+       <programlisting>
+         <command>make</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>--with-libstdc++</command></term>
+         <listitem>
+           <para>
+             Allow linking with libstdc++. <emphasis>(Default = no)</emphasis>
+           </para>
+           <para>
+             This option enables or disables linking HarfBuzz to the
+             system's libstdc++ library.
+           </para>
+         </listitem>
+       </varlistentry>
+       
+       <varlistentry>
+         <term><command>--with-glib</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>--with-gobject</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>--with-cairo</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>--with-fontconfig</command></term>
+         <listitem>
+           <para>
+             Use <ulink url="https://www.freedesktop.org/wiki/Software/fontconfig/">Fontconfig</ulink>. <emphasis>(Default = auto)</emphasis>
+           </para>         
+           <para>
+             This option enables or disables usage of the Fontconfig
+             library, which provides font-matching functions and
+             provides access to font properties. The default setting
+             is to check for the presence of Fontconfig and, if it is
+             found, build with Fontconfig support.
+           </para>
+           <para>
+             Note: Fontconfig is used only by the HarfBuzz
+             command-line utilities, and not by the HarfBuzz library.
+           </para>
+         </listitem>
+       </varlistentry>
+       
+       <varlistentry>
+         <term><command>--with-icu</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>--with-ucdn</command></term>
+         <listitem>
+           <para>
+             Use HarfBuzz's <ulink url="https://github.com/harfbuzz/harfbuzz/tree/master/src/hb-ucdn">built-in UCDN library</ulink>. <emphasis>(Default = auto)</emphasis>
+           </para>         
+           <para>
+             The HarfBuzz source tree includes a <emphasis>Unicode
+             Database and Normalization</emphasis> (UCDN) library
+             that provides access to basic character properties in
+             the Unicode Character Database (UCD) as well as low-level
+             normalization functions. HarfBuzz can be built without
+             this UCDN support if the usage of a different UCDN
+             library is desired.
+           </para>
+         </listitem>
+       </varlistentry>
+       
+       <varlistentry>
+         <term><command>--with-graphite2</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>--with-freetype</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>--with-uniscribe</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>--with-directwrite</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>--with-coretext</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> 
+      </variablelist>
+    </section>
+    
   </section>
 </chapter>
index 470bab8..51ff55a 100644 (file)
@@ -1,3 +1,9 @@
+<?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>
   <section id="opentype-features">
@@ -10,4 +16,4 @@
     <para>
     </para>
   </section>
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/docs/usermanual-shaping-concepts.xml b/docs/usermanual-shaping-concepts.xml
new file mode 100644 (file)
index 0000000..db4e309
--- /dev/null
@@ -0,0 +1,375 @@
+<?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 <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="complex-scripts">
+    <title>Complex scripts</title>
+    <para>
+      In text-shaping terminology, scripts are generally classified as
+      either <emphasis>complex</emphasis> or <emphasis>non-complex</emphasis>.
+    </para>
+    <para>
+      Complex scripts are those for which transforming the input
+      sequence into the final layout 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 complex scripts, the shaping rules require that a text
+      run be divided into syllables before the operations can be
+      applied. Other complex scripts may apply shaping operations over
+      entire words or over the entire text run, with no subdivision
+      required.
+    </para>
+    <para>
+      Non-complex scripts, by definition, do not require these
+      operations. However, correctly shaping a text run in a
+      non-complex script may still involve Unicode normalization,
+      ligature substitutions, mark positioning, kerning, and applying
+      other font features. The key difference is that a text run in a
+      non-complex script can be processed sequentially and in the same
+      order as the input sequence of Unicode codepoints, without
+      requiring an analysis stage.
+    </para>
+  </section>
+  
+  <section id="shaping-operations">
+    <title>Shaping operations</title>
+    <para>
+      Shaping a complex-script 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 complex-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 complex 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 complex 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 complex
+         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 complex 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
+         non-complex scripts, 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, Telugu, and Sinhala.
+       </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 complex 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>
index 38f40cf..ed053f9 100644 (file)
+<?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>. It solves
-    the problem of selecting and positioning glyphs from a font given a
-    Unicode string.
+    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>
-  <section id="why-do-i-need-it">
-    <title>Why do I need it?</title>
+  <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>
-      Text shaping is an integral part of preparing text for display. It
-      is a fairly low level operation; HarfBuzz is used directly by
-      graphic rendering libraries such as Pango, and 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 higher level
-      libraries will turn text into glyphs for you.
+      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, you will need to perform text
-      shaping, and this is where HarfBuzz can help you. Here are some
-      reasons why you need it:
+      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, indexed by glyph ID.
-          The glyph ID within the font does not necessarily relate to a
-          Unicode codepoint. For instance, some fonts have the letter
-          &quot;a&quot; as glyph ID 1. To pull the right glyph out of
-          the font in order to display it, you need to consult a table
-          within the font (the &quot;cmap&quot; table) which maps
-          Unicode codepoints to glyph IDs. Text shaping turns codepoints
-          into glyph IDs.
+          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 which are rendered together. For instance, it's
-          common for the <literal>fi</literal> combination to appear in
-          print as the single ligature &quot;fi&quot;. Whether you should
-          render text as <literal>fi</literal> or &quot;fi&quot; does not
-          depend on the input text, but on the capabilities of the font
-          and the level of ligature application you wish to perform.
-          Text shaping involves querying the font's ligature tables and
-          determining what substitutions should be made.
+          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 typographic
-          refinements, some languages <emphasis>require</emphasis> such
+          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.
-          In Tamil, when the letter &quot;TTA&quot; (ட) letter is
-          followed by &quot;U&quot; (உ), the combination should appear
-          as the single glyph &quot;டு&quot;. The sequence of Unicode
-          characters &quot;டஉ&quot; needs to be rendered as a single
-          glyph from the font - text shaping chooses the correct glyph
-          from the sequence of characters provided.
+        </para>
+       <para>
+         For example, in Tamil, when the letter &quot;TTA&quot; (ட)
+         letter is followed by &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:
-          within a font, there will be glyphs for the initial, medial,
-          final, and isolated forms of each letter. Unicode only encodes
-          one codepoint per character, and so a Unicode string will not
-          tell you which glyph to use. Text shaping chooses the correct
-          form of the letter and returns the correct glyph from the font
-          that you need to render.
+          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 have marks and accents which need to be
-          rendered in certain positions around a base character. For
-          instance, the Moldovan language has the Cyrillic letter
-          &quot;zhe&quot; (ж) with a breve accent, like so: ӂ. Some
-          fonts will contain this character as an individual glyph,
-          whereas other fonts will not contain a zhe-with-breve glyph
-          but expect the rendering engine to form the character by
-          overlaying the two glyphs ж and ˘. Where you should draw the
-          combining breve depends on the height of the preceding glyph.
-          Again, for Arabic, the correct positioning of vowel marks
-          depends on the height of the character on which you are
-          placing the mark. 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, and if so, where to
-          position those marks.
+          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>
+    <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, Telugu, and
+         Sinhala)
+       </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>
-      If this is something that you need to do, then you need a text
-      shaping engine: you could use Uniscribe if you are using Windows;
-      you could use CoreText on OS X; or you could use HarfBuzz. In the
-      rest of this manual, we are going to assume that you are the
-      implementor of a text layout engine.
+      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
-      abstracted out to its own project. This project is maintained by
-      Behdad Esfahbod, and named HarfBuzz. Originally, it was a shaping
-      engine for OpenType fonts - &quot;HarfBuzz&quot; is the Persian
-      for &quot;open type&quot;.
+      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>
\ No newline at end of file
+</chapter>
index a8fdfda..2bf1c1c 100644 (file)
@@ -1 +1 @@
-1.8.1
+2.3.1
index e4a12a5..2454c28 100644 (file)
@@ -196,6 +196,7 @@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_con
          if test -f $(abs_builddir)/$$file ; then \
            cp $(abs_builddir)/$$file $(abs_builddir)/html; \
          fi; \
+         test -f $$file && cp $$file $(abs_builddir)/html; \
        done;
        $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
        $(AM_V_at)touch html-build.stamp
diff --git a/m4/pkg.m4 b/m4/pkg.m4
deleted file mode 100644 (file)
index 0048a3f..0000000
--- a/m4/pkg.m4
+++ /dev/null
@@ -1,157 +0,0 @@
-# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
-# 
-# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
-#
-# 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
-AC_DEFUN([PKG_PROG_PKG_CONFIG],
-[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
-AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
-       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
-fi
-if test -n "$PKG_CONFIG"; then
-       _pkg_min_version=m4_default([$1], [0.9.0])
-       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
-       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
-               AC_MSG_RESULT([yes])
-       else
-               AC_MSG_RESULT([no])
-               PKG_CONFIG=""
-       fi
-               
-fi[]dnl
-])# PKG_PROG_PKG_CONFIG
-
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists.  Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-#
-# Similar to PKG_CHECK_MODULES, make sure that the first instance of
-# this or PKG_CHECK_MODULES is called, or make sure to call
-# PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_EXISTS],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-if test -n "$PKG_CONFIG" && \
-    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
-  m4_ifval([$2], [$2], [:])
-m4_ifvaln([$3], [else
-  $3])dnl
-fi])
-
-
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
-m4_define([_PKG_CONFIG],
-[if test -n "$PKG_CONFIG"; then
-    if test -n "$$1"; then
-        pkg_cv_[]$1="$$1"
-    else
-        PKG_CHECK_EXISTS([$3],
-                         [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
-                        [pkg_failed=yes])
-    fi
-else
-       pkg_failed=untried
-fi[]dnl
-])# _PKG_CONFIG
-
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
-AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
-
-
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_MODULES],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
-AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
-
-pkg_failed=no
-AC_MSG_CHECKING([for $1])
-
-_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
-_PKG_CONFIG([$1][_LIBS], [libs], [$2])
-
-m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
-and $1[]_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.])
-
-if test $pkg_failed = yes; then
-        _PKG_SHORT_ERRORS_SUPPORTED
-        if test $_pkg_short_errors_supported = yes; then
-               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
-        else 
-               $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
-
-       ifelse([$4], , [AC_MSG_ERROR(dnl
-[Package requirements ($2) were not met:
-
-$$1_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-_PKG_TEXT
-])],
-               [AC_MSG_RESULT([no])
-                $4])
-elif test $pkg_failed = untried; then
-       ifelse([$4], , [AC_MSG_FAILURE(dnl
-[The pkg-config script could not be found or is too old.  Make sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-_PKG_TEXT
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
-               [$4])
-else
-       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
-       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
-        AC_MSG_RESULT([yes])
-       ifelse([$3], , :, [$3])
-fi[]dnl
-])# PKG_CHECK_MODULES
index 9d5662e..4a130e1 100644 (file)
@@ -13,8 +13,8 @@ TESTS =
 check_PROGRAMS =
 
 # Convenience targets:
-lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
-fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
+lib: $(BUILT_SOURCES) libharfbuzz.la
+libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
 
 lib_LTLIBRARIES = libharfbuzz.la
 
@@ -28,12 +28,6 @@ HBSOURCES =  $(HB_BASE_sources)
 HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
 HBHEADERS = $(HB_BASE_headers)
 
-if HAVE_OT
-HBSOURCES += $(HB_OT_sources)
-HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources)
-HBHEADERS += $(HB_OT_headers)
-endif
-
 if HAVE_FALLBACK
 HBSOURCES += $(HB_FALLBACK_sources)
 endif
@@ -170,37 +164,6 @@ pkginclude_HEADERS += $(HB_SUBSET_headers)
 pkgconfig_DATA += harfbuzz-subset.pc
 EXTRA_DIST += harfbuzz-subset.pc.in
 
-FUZZING_CPPFLAGS = \
-       -DHB_NDEBUG \
-       -DHB_MAX_NESTING_LEVEL=3 \
-       -DHB_SANITIZE_MAX_EDITS=3 \
-       -DHB_SANITIZE_MAX_OPS_FACTOR=3 \
-       -DHB_SANITIZE_MAX_OPS_MIN=128 \
-       -DHB_BUFFER_MAX_LEN_FACTOR=3 \
-       -DHB_BUFFER_MAX_LEN_MIN=8 \
-       -DHB_BUFFER_MAX_LEN_DEFAULT=128 \
-       -DHB_BUFFER_MAX_OPS_FACTOR=8 \
-       -DHB_BUFFER_MAX_OPS_MIN=64 \
-       -DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
-       $(NULL)
-EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
-
-libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS)
-libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
-libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
-libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
-libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
-EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
-CLEANFILES += libharfbuzz-fuzzing.la
-
-libharfbuzz_subset_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_subset_fuzzing_la_LDFLAGS)
-libharfbuzz_subset_fuzzing_la_SOURCES = $(libharfbuzz_subset_la_SOURCES)
-libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
-libharfbuzz_subset_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
-libharfbuzz_subset_fuzzing_la_LIBADD = $(libharfbuzz_subset_la_LIBADD)
-EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES)
-CLEANFILES += libharfbuzz-subset-fuzzing.la
-
 if HAVE_ICU
 if HAVE_ICU_BUILTIN
 HBCFLAGS += $(ICU_CFLAGS)
@@ -270,31 +233,37 @@ EXTRA_DIST += \
 CLEANFILES += $(pkgconfig_DATA)
 
 
-DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def
+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: $(HBHEADERS) $(HBNODISTHEADERS)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-subset.def: $(HB_SUBSET_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-icu.def: $(HB_ICU_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-gobject.def: $(HB_GOBJECT_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(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-table.py \
+       gen-def.py \
+       gen-emoji-table.py \
        gen-indic-table.py \
+       gen-os2-unicode-ranges.py \
+       gen-tag-table.py \
        gen-use-table.py \
-       gen-def.py \
+       gen-vowel-constraints.py \
        $(NULL)
 EXTRA_DIST += $(GENERATORS)
 
-unicode-tables: arabic-table indic-table use-table
+unicode-tables: arabic-table indic-table tag-table use-table emoji-table
 
 arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
@@ -304,22 +273,32 @@ indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategor
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
        || ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
 
+tag-table: gen-tag-table.py languagetags language-subtag-registry
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
+       || ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
+
 use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
        || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
 
+vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
+       || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
+
+emoji-table: gen-emoji-table.py emoji-data.txt
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
+       || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
+
 built-sources: $(BUILT_SOURCES)
 
-.PHONY: unicode-tables arabic-table indic-table use-table built-sources
+.PHONY: unicode-tables arabic-table indic-table tag-table use-table vowel-constraints emoji-table built-sources
 
 RAGEL_GENERATED = \
        $(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
-       $(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \
        $(NULL)
 BUILT_SOURCES += $(RAGEL_GENERATED)
 EXTRA_DIST += \
        $(HB_BASE_RAGEL_sources) \
-       $(HB_OT_RAGEL_sources) \
        $(NULL)
 # We decided to add ragel-generated files to git...
 #MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
@@ -331,6 +310,7 @@ noinst_PROGRAMS = \
        main \
        test \
        test-buffer-serialize \
+       test-name-table \
        test-size-params \
        test-would-substitute \
        $(NULL)
@@ -344,17 +324,30 @@ test_SOURCES = test.cc
 test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
 test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
 
-test_would_substitute_SOURCES = test-would-substitute.cc
-test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
-test_would_substitute_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_name_table_SOURCES = test-name-table.cc
+test_name_table_CPPFLAGS = $(HBCFLAGS)
+test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
 
 test_size_params_SOURCES = test-size-params.cc
 test_size_params_CPPFLAGS = $(HBCFLAGS)
 test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
 
-test_buffer_serialize_SOURCES = test-buffer-serialize.cc
-test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
-test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
+test_would_substitute_SOURCES = test-would-substitute.cc
+test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+
+if HAVE_FREETYPE
+if HAVE_CAIRO_FT
+noinst_PROGRAMS += test-ot-color
+test_ot_color_SOURCES = test-ot-color.cc
+test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
+test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
+endif # HAVE_CAIRO_FT
+endif # HAVE_FREETYPE
 
 dist_check_SCRIPTS = \
        check-c-linkage-decls.sh \
@@ -373,15 +366,11 @@ dist_check_SCRIPTS += \
 endif
 
 check_PROGRAMS += \
-       dump-fon \
        dump-indic-data \
        dump-khmer-data \
        dump-myanmar-data \
        dump-use-data \
        $(NULL)
-dump_fon_SOURCES = dump-fon.cc
-dump_fon_CPPFLAGS = $(HBCFLAGS)
-dump_fon_LDADD = libharfbuzz.la $(HBLIBS)
 dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
 dump_indic_data_CPPFLAGS = $(HBCFLAGS)
 dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
@@ -395,24 +384,23 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
 dump_use_data_CPPFLAGS = $(HBCFLAGS)
 dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
 
-if HAVE_FREETYPE
-if HAVE_CAIRO_FT
-check_PROGRAMS += dump-emoji
-dump_emoji_SOURCES = dump-emoji.cc
-dump_emoji_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
-dump_emoji_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
-endif # HAVE_CAIRO_FT
-endif # HAVE_FREETYPE
+COMPILED_TESTS = test-iter test-ot-tag test-unicode-ranges
+COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
+COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
+check_PROGRAMS += $(COMPILED_TESTS)
+TESTS += $(COMPILED_TESTS)
 
-check_PROGRAMS += test-ot-tag test-unicode-ranges
-TESTS += test-ot-tag test-unicode-ranges
+test_iter_SOURCES = test-iter.cc hb-static.cc
+test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_iter_LDADD = $(COMPILED_TESTS_LDADD)
 
 test_ot_tag_SOURCES = hb-ot-tag.cc
-test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
-test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
+test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
 
 test_unicode_ranges_SOURCES = test-unicode-ranges.cc
-test_unicode_ranges_LDADD = libharfbuzz.la $(HBLIBS)
+test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
 
 TESTS_ENVIRONMENT = \
        srcdir="$(srcdir)" \
@@ -438,6 +426,8 @@ HarfBuzz_0_0_gir_CFLAGS = \
        -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= \
index e3715e8..beba71c 100644 (file)
@@ -95,86 +95,82 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-TESTS = $(am__EXEEXT_4) test-ot-tag$(EXEEXT) \
-       test-unicode-ranges$(EXEEXT)
-check_PROGRAMS = dump-fon$(EXEEXT) dump-indic-data$(EXEEXT) \
-       dump-khmer-data$(EXEEXT) dump-myanmar-data$(EXEEXT) \
-       dump-use-data$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \
-       test-ot-tag$(EXEEXT) test-unicode-ranges$(EXEEXT)
-@HAVE_OT_TRUE@am__append_1 = $(HB_OT_sources) \
-@HAVE_OT_TRUE@ $(HB_OT_RAGEL_GENERATED_sources)
-@HAVE_OT_TRUE@am__append_2 = $(HB_OT_headers)
-@HAVE_FALLBACK_TRUE@am__append_3 = $(HB_FALLBACK_sources)
-@HAVE_PTHREAD_TRUE@am__append_4 = $(PTHREAD_CFLAGS)
-@HAVE_PTHREAD_TRUE@am__append_5 = $(PTHREAD_LIBS)
-@HAVE_GLIB_TRUE@am__append_6 = $(GLIB_CFLAGS)
-@HAVE_GLIB_TRUE@am__append_7 = $(GLIB_LIBS)
-@HAVE_GLIB_TRUE@am__append_8 = $(GLIB_DEPS)
-@HAVE_GLIB_TRUE@am__append_9 = $(HB_GLIB_sources)
-@HAVE_GLIB_TRUE@am__append_10 = $(HB_GLIB_headers)
-@HAVE_FREETYPE_TRUE@am__append_11 = $(FREETYPE_CFLAGS)
-@HAVE_FREETYPE_TRUE@am__append_12 = $(FREETYPE_LIBS)
+TESTS = $(am__EXEEXT_5) $(am__EXEEXT_2)
+check_PROGRAMS = dump-indic-data$(EXEEXT) dump-khmer-data$(EXEEXT) \
+       dump-myanmar-data$(EXEEXT) dump-use-data$(EXEEXT) \
+       $(am__EXEEXT_1) $(am__EXEEXT_2)
+@HAVE_FALLBACK_TRUE@am__append_1 = $(HB_FALLBACK_sources)
+@HAVE_PTHREAD_TRUE@am__append_2 = $(PTHREAD_CFLAGS)
+@HAVE_PTHREAD_TRUE@am__append_3 = $(PTHREAD_LIBS)
+@HAVE_GLIB_TRUE@am__append_4 = $(GLIB_CFLAGS)
+@HAVE_GLIB_TRUE@am__append_5 = $(GLIB_LIBS)
+@HAVE_GLIB_TRUE@am__append_6 = $(GLIB_DEPS)
+@HAVE_GLIB_TRUE@am__append_7 = $(HB_GLIB_sources)
+@HAVE_GLIB_TRUE@am__append_8 = $(HB_GLIB_headers)
+@HAVE_FREETYPE_TRUE@am__append_9 = $(FREETYPE_CFLAGS)
+@HAVE_FREETYPE_TRUE@am__append_10 = $(FREETYPE_LIBS)
 # XXX
 # The following creates a recursive dependency on FreeType if FreeType is
 # built with HarfBuzz support enabled.  Newer pkg-config handles that just
 # fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes.  Remove
 # in a year or two, or otherwise work around it...
 #HBDEPS   += $(FREETYPE_DEPS)
-@HAVE_FREETYPE_TRUE@am__append_13 = $(HB_FT_sources)
-@HAVE_FREETYPE_TRUE@am__append_14 = $(HB_FT_headers)
-@HAVE_GRAPHITE2_TRUE@am__append_15 = $(GRAPHITE2_CFLAGS)
-@HAVE_GRAPHITE2_TRUE@am__append_16 = $(GRAPHITE2_LIBS)
-@HAVE_GRAPHITE2_TRUE@am__append_17 = $(GRAPHITE2_DEPS)
-@HAVE_GRAPHITE2_TRUE@am__append_18 = $(HB_GRAPHITE2_sources)
-@HAVE_GRAPHITE2_TRUE@am__append_19 = $(HB_GRAPHITE2_headers)
-@HAVE_UNISCRIBE_TRUE@am__append_20 = $(UNISCRIBE_CFLAGS)
-@HAVE_UNISCRIBE_TRUE@am__append_21 = $(UNISCRIBE_LIBS)
-@HAVE_UNISCRIBE_TRUE@am__append_22 = $(HB_UNISCRIBE_sources)
-@HAVE_UNISCRIBE_TRUE@am__append_23 = $(HB_UNISCRIBE_headers)
-@HAVE_DIRECTWRITE_TRUE@am__append_24 = $(DIRECTWRITE_CXXFLAGS)
-@HAVE_DIRECTWRITE_TRUE@am__append_25 = $(DIRECTWRITE_LIBS)
-@HAVE_DIRECTWRITE_TRUE@am__append_26 = $(HB_DIRECTWRITE_sources)
-@HAVE_DIRECTWRITE_TRUE@am__append_27 = $(HB_DIRECTWRITE_headers)
-@HAVE_CORETEXT_TRUE@am__append_28 = $(CORETEXT_CFLAGS)
-@HAVE_CORETEXT_TRUE@am__append_29 = $(CORETEXT_LIBS)
-@HAVE_CORETEXT_TRUE@am__append_30 = $(HB_CORETEXT_sources)
-@HAVE_CORETEXT_TRUE@am__append_31 = $(HB_CORETEXT_headers)
-@HAVE_UCDN_TRUE@am__append_32 = hb-ucdn
-@HAVE_UCDN_TRUE@am__append_33 = -I$(srcdir)/hb-ucdn
-@HAVE_UCDN_TRUE@am__append_34 = hb-ucdn/libhb-ucdn.la
-@HAVE_UCDN_TRUE@am__append_35 = $(HB_UCDN_sources)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_36 = $(ICU_CFLAGS)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_37 = $(ICU_LIBS)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_38 = $(HB_ICU_sources)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_39 = $(HB_ICU_headers)
-@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_40 = libharfbuzz-icu.la
-@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_41 = $(HB_ICU_headers)
-@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_42 = harfbuzz-icu.pc
-@HAVE_GOBJECT_TRUE@am__append_43 = libharfbuzz-gobject.la
-@HAVE_GOBJECT_TRUE@am__append_44 = $(HB_GOBJECT_DIST_headers)
-@HAVE_GOBJECT_TRUE@am__append_45 = $(HB_GOBJECT_NODIST_headers)
-@HAVE_GOBJECT_TRUE@am__append_46 = harfbuzz-gobject.pc
-@HAVE_GOBJECT_TRUE@am__append_47 = \
+@HAVE_FREETYPE_TRUE@am__append_11 = $(HB_FT_sources)
+@HAVE_FREETYPE_TRUE@am__append_12 = $(HB_FT_headers)
+@HAVE_GRAPHITE2_TRUE@am__append_13 = $(GRAPHITE2_CFLAGS)
+@HAVE_GRAPHITE2_TRUE@am__append_14 = $(GRAPHITE2_LIBS)
+@HAVE_GRAPHITE2_TRUE@am__append_15 = $(GRAPHITE2_DEPS)
+@HAVE_GRAPHITE2_TRUE@am__append_16 = $(HB_GRAPHITE2_sources)
+@HAVE_GRAPHITE2_TRUE@am__append_17 = $(HB_GRAPHITE2_headers)
+@HAVE_UNISCRIBE_TRUE@am__append_18 = $(UNISCRIBE_CFLAGS)
+@HAVE_UNISCRIBE_TRUE@am__append_19 = $(UNISCRIBE_LIBS)
+@HAVE_UNISCRIBE_TRUE@am__append_20 = $(HB_UNISCRIBE_sources)
+@HAVE_UNISCRIBE_TRUE@am__append_21 = $(HB_UNISCRIBE_headers)
+@HAVE_DIRECTWRITE_TRUE@am__append_22 = $(DIRECTWRITE_CXXFLAGS)
+@HAVE_DIRECTWRITE_TRUE@am__append_23 = $(DIRECTWRITE_LIBS)
+@HAVE_DIRECTWRITE_TRUE@am__append_24 = $(HB_DIRECTWRITE_sources)
+@HAVE_DIRECTWRITE_TRUE@am__append_25 = $(HB_DIRECTWRITE_headers)
+@HAVE_CORETEXT_TRUE@am__append_26 = $(CORETEXT_CFLAGS)
+@HAVE_CORETEXT_TRUE@am__append_27 = $(CORETEXT_LIBS)
+@HAVE_CORETEXT_TRUE@am__append_28 = $(HB_CORETEXT_sources)
+@HAVE_CORETEXT_TRUE@am__append_29 = $(HB_CORETEXT_headers)
+@HAVE_UCDN_TRUE@am__append_30 = hb-ucdn
+@HAVE_UCDN_TRUE@am__append_31 = -I$(srcdir)/hb-ucdn
+@HAVE_UCDN_TRUE@am__append_32 = hb-ucdn/libhb-ucdn.la
+@HAVE_UCDN_TRUE@am__append_33 = $(HB_UCDN_sources)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_34 = $(ICU_CFLAGS)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_35 = $(ICU_LIBS)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_36 = $(HB_ICU_sources)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__append_37 = $(HB_ICU_headers)
+@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_38 = libharfbuzz-icu.la
+@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_39 = $(HB_ICU_headers)
+@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am__append_40 = harfbuzz-icu.pc
+@HAVE_GOBJECT_TRUE@am__append_41 = libharfbuzz-gobject.la
+@HAVE_GOBJECT_TRUE@am__append_42 = $(HB_GOBJECT_DIST_headers)
+@HAVE_GOBJECT_TRUE@am__append_43 = $(HB_GOBJECT_NODIST_headers)
+@HAVE_GOBJECT_TRUE@am__append_44 = harfbuzz-gobject.pc
+@HAVE_GOBJECT_TRUE@am__append_45 = \
 @HAVE_GOBJECT_TRUE@    $(HB_GOBJECT_ENUM_sources) \
 @HAVE_GOBJECT_TRUE@    $(HB_GOBJECT_ENUM_headers) \
 @HAVE_GOBJECT_TRUE@    $(NULL)
 
-@HAVE_GOBJECT_TRUE@am__append_48 = \
+@HAVE_GOBJECT_TRUE@am__append_46 = \
 @HAVE_GOBJECT_TRUE@    $(HB_GOBJECT_ENUM_sources) \
 @HAVE_GOBJECT_TRUE@    $(HB_GOBJECT_ENUM_headers) \
 @HAVE_GOBJECT_TRUE@    $(NULL)
 
-@HAVE_GOBJECT_TRUE@am__append_49 = harfbuzz-gobject.def
+@HAVE_GOBJECT_TRUE@am__append_47 = harfbuzz-gobject.def
 noinst_PROGRAMS = main$(EXEEXT) test$(EXEEXT) \
-       test-buffer-serialize$(EXEEXT) test-size-params$(EXEEXT) \
-       test-would-substitute$(EXEEXT) $(am__EXEEXT_1)
+       test-buffer-serialize$(EXEEXT) test-name-table$(EXEEXT) \
+       test-size-params$(EXEEXT) test-would-substitute$(EXEEXT) \
+       $(am__EXEEXT_1) $(am__EXEEXT_3)
 bin_PROGRAMS =
-@WITH_LIBSTDCXX_FALSE@am__append_50 = \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am__append_48 = test-ot-color
+@WITH_LIBSTDCXX_FALSE@am__append_49 = \
 @WITH_LIBSTDCXX_FALSE@ check-libstdc++.sh \
 @WITH_LIBSTDCXX_FALSE@ $(NULL)
 
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am__append_51 = dump-emoji
-@HAVE_INTROSPECTION_TRUE@am__append_52 = $(gir_DATA) $(typelib_DATA)
+@HAVE_INTROSPECTION_TRUE@am__append_50 = $(gir_DATA) $(typelib_DATA)
 subdir = src
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
@@ -182,8 +178,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_check_SCRIPTS_DIST) \
@@ -225,177 +220,16 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
        "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"
 LTLIBRARIES = $(lib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
-@HAVE_GLIB_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-@HAVE_FREETYPE_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
-@HAVE_GRAPHITE2_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
-@HAVE_PTHREAD_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1)
-@HAVE_UNISCRIBE_TRUE@am__DEPENDENCIES_6 = $(am__DEPENDENCIES_1)
-@HAVE_DIRECTWRITE_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1)
-@HAVE_CORETEXT_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_1)
-am__DEPENDENCIES_9 = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \
-       $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_8)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__DEPENDENCIES_10 =  \
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__DEPENDENCIES_1)
-am__DEPENDENCIES_11 = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
-       $(am__DEPENDENCIES_4) $(am__append_34) $(am__DEPENDENCIES_9) \
-       $(am__DEPENDENCIES_10)
-am__DEPENDENCIES_12 = $(am__DEPENDENCIES_11)
-libharfbuzz_fuzzing_la_DEPENDENCIES = $(am__DEPENDENCIES_12)
-am__libharfbuzz_fuzzing_la_SOURCES_DIST = hb-atomic-private.hh \
-       hb-blob-private.hh hb-blob.cc hb-buffer-private.hh \
-       hb-buffer-serialize.cc hb-buffer.cc hb-common.cc hb-debug.hh \
-       hb-dsalgs.hh hb-face-private.hh hb-face.cc hb-font-private.hh \
-       hb-font.cc hb-map-private.hh hb-map.cc hb-mutex-private.hh \
-       hb-object-private.hh hb-open-file-private.hh \
-       hb-open-type-private.hh hb-ot-color-cbdt-table.hh \
-       hb-ot-cmap-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-maxp-table.hh hb-ot-name-table.hh \
-       hb-ot-os2-table.hh hb-ot-os2-unicode-ranges.hh \
-       hb-ot-post-macroman.hh hb-ot-post-table.hh hb-ot-tag.cc \
-       hb-private.hh hb-set-digest-private.hh hb-set-private.hh \
-       hb-set.cc hb-shape.cc hb-shape-plan-private.hh \
-       hb-shape-plan.cc hb-shaper-list.hh hb-shaper-impl-private.hh \
-       hb-shaper-private.hh hb-shaper.cc hb-static.cc \
-       hb-string-array.hh hb-unicode-private.hh hb-unicode.cc \
-       hb-utf-private.hh hb-warning.cc hb-buffer-deserialize-json.hh \
-       hb-buffer-deserialize-text.hh hb-aat-layout.cc \
-       hb-aat-layout-common-private.hh hb-aat-layout-ankr-table.hh \
-       hb-aat-layout-bsln-table.hh hb-aat-layout-feat-table.hh \
-       hb-aat-layout-kerx-table.hh hb-aat-layout-morx-table.hh \
-       hb-aat-layout-trak-table.hh hb-aat-layout-private.hh \
-       hb-aat-fmtx-table.hh hb-aat-gcid-table.hh hb-aat-ltag-table.hh \
-       hb-ot-font.cc hb-ot-layout.cc hb-ot-layout-base-table.hh \
-       hb-ot-layout-common-private.hh hb-ot-layout-gdef-table.hh \
-       hb-ot-layout-gpos-table.hh hb-ot-layout-gsubgpos-private.hh \
-       hb-ot-layout-gsub-table.hh hb-ot-layout-jstf-table.hh \
-       hb-ot-layout-private.hh hb-ot-color.cc \
-       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-map.cc hb-ot-map-private.hh hb-ot-math.cc \
-       hb-ot-math-table.hh hb-ot-shape.cc \
-       hb-ot-shape-complex-arabic.cc \
-       hb-ot-shape-complex-arabic-fallback.hh \
-       hb-ot-shape-complex-arabic-private.hh \
-       hb-ot-shape-complex-arabic-table.hh \
-       hb-ot-shape-complex-arabic-win1256.hh \
-       hb-ot-shape-complex-default.cc hb-ot-shape-complex-hangul.cc \
-       hb-ot-shape-complex-hebrew.cc hb-ot-shape-complex-indic.cc \
-       hb-ot-shape-complex-indic-private.hh \
-       hb-ot-shape-complex-indic-table.cc \
-       hb-ot-shape-complex-khmer-private.hh \
-       hb-ot-shape-complex-khmer.cc \
-       hb-ot-shape-complex-myanmar-private.hh \
-       hb-ot-shape-complex-myanmar.cc hb-ot-shape-complex-thai.cc \
-       hb-ot-shape-complex-tibetan.cc hb-ot-shape-complex-use.cc \
-       hb-ot-shape-complex-use-private.hh \
-       hb-ot-shape-complex-use-table.cc \
-       hb-ot-shape-complex-private.hh \
-       hb-ot-shape-normalize-private.hh hb-ot-shape-normalize.cc \
-       hb-ot-shape-fallback-private.hh hb-ot-shape-fallback.cc \
-       hb-ot-shape-private.hh hb-ot-var.cc hb-ot-var-avar-table.hh \
-       hb-ot-var-fvar-table.hh hb-ot-var-hvar-table.hh \
-       hb-ot-var-mvar-table.hh hb-ot-shape-complex-indic-machine.hh \
-       hb-ot-shape-complex-khmer-machine.hh \
-       hb-ot-shape-complex-myanmar-machine.hh \
-       hb-ot-shape-complex-use-machine.hh hb-fallback-shape.cc \
-       hb-glib.cc hb-ft.cc hb-graphite2.cc hb-uniscribe.cc \
-       hb-directwrite.cc hb-coretext.cc hb-ucdn.cc hb-icu.cc hb.h \
-       hb-blob.h hb-buffer.h hb-common.h hb-deprecated.h hb-face.h \
-       hb-font.h hb-map.h hb-set.h hb-shape.h hb-shape-plan.h \
-       hb-unicode.h hb-version.h hb-ot.h hb-ot-font.h hb-ot-layout.h \
-       hb-ot-math.h hb-ot-shape.h hb-ot-tag.h hb-ot-var.h hb-glib.h \
-       hb-ft.h hb-graphite2.h hb-uniscribe.h hb-directwrite.h \
-       hb-coretext.h hb-icu.h
-am__objects_1 =
-am__objects_2 = libharfbuzz_fuzzing_la-hb-blob.lo \
-       libharfbuzz_fuzzing_la-hb-buffer-serialize.lo \
-       libharfbuzz_fuzzing_la-hb-buffer.lo \
-       libharfbuzz_fuzzing_la-hb-common.lo \
-       libharfbuzz_fuzzing_la-hb-face.lo \
-       libharfbuzz_fuzzing_la-hb-font.lo \
-       libharfbuzz_fuzzing_la-hb-map.lo \
-       libharfbuzz_fuzzing_la-hb-ot-tag.lo \
-       libharfbuzz_fuzzing_la-hb-set.lo \
-       libharfbuzz_fuzzing_la-hb-shape.lo \
-       libharfbuzz_fuzzing_la-hb-shape-plan.lo \
-       libharfbuzz_fuzzing_la-hb-shaper.lo \
-       libharfbuzz_fuzzing_la-hb-static.lo \
-       libharfbuzz_fuzzing_la-hb-unicode.lo \
-       libharfbuzz_fuzzing_la-hb-warning.lo $(am__objects_1)
-am__objects_3 = $(am__objects_1)
-am__objects_4 = libharfbuzz_fuzzing_la-hb-aat-layout.lo \
-       libharfbuzz_fuzzing_la-hb-ot-font.lo \
-       libharfbuzz_fuzzing_la-hb-ot-layout.lo \
-       libharfbuzz_fuzzing_la-hb-ot-color.lo \
-       libharfbuzz_fuzzing_la-hb-ot-map.lo \
-       libharfbuzz_fuzzing_la-hb-ot-math.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo \
-       libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo \
-       libharfbuzz_fuzzing_la-hb-ot-var.lo $(am__objects_1)
-@HAVE_OT_TRUE@am__objects_5 = $(am__objects_4) $(am__objects_3)
-am__objects_6 = libharfbuzz_fuzzing_la-hb-fallback-shape.lo \
-       $(am__objects_1)
-@HAVE_FALLBACK_TRUE@am__objects_7 = $(am__objects_6)
-am__objects_8 = libharfbuzz_fuzzing_la-hb-glib.lo
-@HAVE_GLIB_TRUE@am__objects_9 = $(am__objects_8)
-am__objects_10 = libharfbuzz_fuzzing_la-hb-ft.lo
-@HAVE_FREETYPE_TRUE@am__objects_11 = $(am__objects_10)
-am__objects_12 = libharfbuzz_fuzzing_la-hb-graphite2.lo
-@HAVE_GRAPHITE2_TRUE@am__objects_13 = $(am__objects_12)
-am__objects_14 = libharfbuzz_fuzzing_la-hb-uniscribe.lo
-@HAVE_UNISCRIBE_TRUE@am__objects_15 = $(am__objects_14)
-am__objects_16 = libharfbuzz_fuzzing_la-hb-directwrite.lo
-@HAVE_DIRECTWRITE_TRUE@am__objects_17 = $(am__objects_16)
-am__objects_18 = libharfbuzz_fuzzing_la-hb-coretext.lo
-@HAVE_CORETEXT_TRUE@am__objects_19 = $(am__objects_18)
-am__objects_20 = libharfbuzz_fuzzing_la-hb-ucdn.lo
-@HAVE_UCDN_TRUE@am__objects_21 = $(am__objects_20)
-am__objects_22 = libharfbuzz_fuzzing_la-hb-icu.lo
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__objects_23 =  \
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__objects_22)
-am__objects_24 = $(am__objects_2) $(am__objects_3) $(am__objects_5) \
-       $(am__objects_7) $(am__objects_9) $(am__objects_11) \
-       $(am__objects_13) $(am__objects_15) $(am__objects_17) \
-       $(am__objects_19) $(am__objects_21) $(am__objects_23)
-@HAVE_OT_TRUE@am__objects_25 = $(am__objects_3)
-@HAVE_GLIB_TRUE@am__objects_26 = $(am__objects_1)
-@HAVE_FREETYPE_TRUE@am__objects_27 = $(am__objects_1)
-@HAVE_GRAPHITE2_TRUE@am__objects_28 = $(am__objects_1)
-@HAVE_UNISCRIBE_TRUE@am__objects_29 = $(am__objects_1)
-@HAVE_DIRECTWRITE_TRUE@am__objects_30 = $(am__objects_1)
-@HAVE_CORETEXT_TRUE@am__objects_31 = $(am__objects_1)
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__objects_32 =  \
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__objects_1)
-am__objects_33 = $(am__objects_3) $(am__objects_25) $(am__objects_26) \
-       $(am__objects_27) $(am__objects_28) $(am__objects_29) \
-       $(am__objects_30) $(am__objects_31) $(am__objects_32)
-am__objects_34 = $(am__objects_24) $(am__objects_33)
-am_libharfbuzz_fuzzing_la_OBJECTS = $(am__objects_34)
-libharfbuzz_fuzzing_la_OBJECTS = $(am_libharfbuzz_fuzzing_la_OBJECTS)
 @HAVE_GOBJECT_TRUE@libharfbuzz_gobject_la_DEPENDENCIES =  \
 @HAVE_GOBJECT_TRUE@    $(am__DEPENDENCIES_1) libharfbuzz.la
 am__libharfbuzz_gobject_la_SOURCES_DIST = hb-gobject-structs.cc
-am__objects_35 = libharfbuzz_gobject_la-hb-gobject-structs.lo
+am__objects_1 = libharfbuzz_gobject_la-hb-gobject-structs.lo
 @HAVE_GOBJECT_TRUE@am_libharfbuzz_gobject_la_OBJECTS =  \
-@HAVE_GOBJECT_TRUE@    $(am__objects_35)
-am__objects_36 = libharfbuzz_gobject_la-hb-gobject-enums.lo
-am__objects_37 = $(am__objects_36)
+@HAVE_GOBJECT_TRUE@    $(am__objects_1)
+am__objects_2 = libharfbuzz_gobject_la-hb-gobject-enums.lo
+am__objects_3 = $(am__objects_2)
 @HAVE_GOBJECT_TRUE@nodist_libharfbuzz_gobject_la_OBJECTS =  \
-@HAVE_GOBJECT_TRUE@    $(am__objects_37)
+@HAVE_GOBJECT_TRUE@    $(am__objects_3)
 libharfbuzz_gobject_la_OBJECTS = $(am_libharfbuzz_gobject_la_OBJECTS) \
        $(nodist_libharfbuzz_gobject_la_OBJECTS)
 @HAVE_GOBJECT_TRUE@am_libharfbuzz_gobject_la_rpath = -rpath $(libdir)
@@ -403,9 +237,9 @@ libharfbuzz_gobject_la_OBJECTS = $(am_libharfbuzz_gobject_la_OBJECTS) \
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@        $(am__DEPENDENCIES_1) \
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@        libharfbuzz.la
 am__libharfbuzz_icu_la_SOURCES_DIST = hb-icu.cc
-am__objects_38 = libharfbuzz_icu_la-hb-icu.lo
+am__objects_4 = libharfbuzz_icu_la-hb-icu.lo
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am_libharfbuzz_icu_la_OBJECTS =  \
-@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@        $(am__objects_38)
+@HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@        $(am__objects_4)
 libharfbuzz_icu_la_OBJECTS = $(am_libharfbuzz_icu_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -417,167 +251,184 @@ libharfbuzz_icu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
        $(LDFLAGS) -o $@
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@am_libharfbuzz_icu_la_rpath =  \
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@        -rpath $(libdir)
-libharfbuzz_subset_fuzzing_la_DEPENDENCIES =  \
-       $(libharfbuzz_subset_la_LIBADD)
-am__objects_39 = libharfbuzz_subset_fuzzing_la-hb-static.lo \
-       libharfbuzz_subset_fuzzing_la-hb-subset.lo \
-       libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo \
-       libharfbuzz_subset_fuzzing_la-hb-subset-input.lo \
-       libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo \
-       $(am__objects_1)
-am__objects_40 = $(am__objects_39)
-am_libharfbuzz_subset_fuzzing_la_OBJECTS = $(am__objects_40)
-libharfbuzz_subset_fuzzing_la_OBJECTS =  \
-       $(am_libharfbuzz_subset_fuzzing_la_OBJECTS)
 libharfbuzz_subset_la_DEPENDENCIES = libharfbuzz.la
-am__objects_41 = libharfbuzz_subset_la-hb-static.lo \
-       libharfbuzz_subset_la-hb-subset.lo \
+am__objects_5 =
+am__objects_6 = libharfbuzz_subset_la-hb-ot-cff1-table.lo \
+       libharfbuzz_subset_la-hb-ot-cff2-table.lo \
+       libharfbuzz_subset_la-hb-static.lo \
+       libharfbuzz_subset_la-hb-subset-cff-common.lo \
+       libharfbuzz_subset_la-hb-subset-cff1.lo \
+       libharfbuzz_subset_la-hb-subset-cff2.lo \
        libharfbuzz_subset_la-hb-subset-glyf.lo \
        libharfbuzz_subset_la-hb-subset-input.lo \
-       libharfbuzz_subset_la-hb-subset-plan.lo $(am__objects_1)
-am_libharfbuzz_subset_la_OBJECTS = $(am__objects_41)
+       libharfbuzz_subset_la-hb-subset-plan.lo \
+       libharfbuzz_subset_la-hb-subset.lo $(am__objects_5)
+am_libharfbuzz_subset_la_OBJECTS = $(am__objects_6)
 libharfbuzz_subset_la_OBJECTS = $(am_libharfbuzz_subset_la_OBJECTS)
 libharfbuzz_subset_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
        $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
        $(AM_CXXFLAGS) $(CXXFLAGS) $(libharfbuzz_subset_la_LDFLAGS) \
        $(LDFLAGS) -o $@
+@HAVE_GLIB_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@HAVE_FREETYPE_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@HAVE_GRAPHITE2_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+@HAVE_PTHREAD_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1)
+@HAVE_UNISCRIBE_TRUE@am__DEPENDENCIES_6 = $(am__DEPENDENCIES_1)
+@HAVE_DIRECTWRITE_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1)
+@HAVE_CORETEXT_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_9 = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \
+       $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_8)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__DEPENDENCIES_10 =  \
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_11 = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
+       $(am__DEPENDENCIES_4) $(am__append_32) $(am__DEPENDENCIES_9) \
+       $(am__DEPENDENCIES_10)
 libharfbuzz_la_DEPENDENCIES = $(am__DEPENDENCIES_11)
-am__libharfbuzz_la_SOURCES_DIST = hb-atomic-private.hh \
-       hb-blob-private.hh hb-blob.cc hb-buffer-private.hh \
-       hb-buffer-serialize.cc hb-buffer.cc hb-common.cc hb-debug.hh \
-       hb-dsalgs.hh hb-face-private.hh hb-face.cc hb-font-private.hh \
-       hb-font.cc hb-map-private.hh hb-map.cc hb-mutex-private.hh \
-       hb-object-private.hh hb-open-file-private.hh \
-       hb-open-type-private.hh hb-ot-color-cbdt-table.hh \
-       hb-ot-cmap-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-maxp-table.hh hb-ot-name-table.hh \
-       hb-ot-os2-table.hh hb-ot-os2-unicode-ranges.hh \
-       hb-ot-post-macroman.hh hb-ot-post-table.hh hb-ot-tag.cc \
-       hb-private.hh hb-set-digest-private.hh hb-set-private.hh \
-       hb-set.cc hb-shape.cc hb-shape-plan-private.hh \
-       hb-shape-plan.cc hb-shaper-list.hh hb-shaper-impl-private.hh \
-       hb-shaper-private.hh hb-shaper.cc hb-static.cc \
-       hb-string-array.hh hb-unicode-private.hh hb-unicode.cc \
-       hb-utf-private.hh hb-warning.cc hb-buffer-deserialize-json.hh \
-       hb-buffer-deserialize-text.hh hb-aat-layout.cc \
-       hb-aat-layout-common-private.hh hb-aat-layout-ankr-table.hh \
-       hb-aat-layout-bsln-table.hh hb-aat-layout-feat-table.hh \
-       hb-aat-layout-kerx-table.hh hb-aat-layout-morx-table.hh \
-       hb-aat-layout-trak-table.hh hb-aat-layout-private.hh \
-       hb-aat-fmtx-table.hh hb-aat-gcid-table.hh hb-aat-ltag-table.hh \
-       hb-ot-font.cc hb-ot-layout.cc hb-ot-layout-base-table.hh \
-       hb-ot-layout-common-private.hh hb-ot-layout-gdef-table.hh \
-       hb-ot-layout-gpos-table.hh hb-ot-layout-gsubgpos-private.hh \
-       hb-ot-layout-gsub-table.hh hb-ot-layout-jstf-table.hh \
-       hb-ot-layout-private.hh hb-ot-color.cc \
+am__libharfbuzz_la_SOURCES_DIST = hb-aat-fdsc-table.hh \
+       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-lcar-table.hh hb-aat-layout-morx-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-array.hh \
+       hb-atomic.hh hb-blob.cc hb-blob.hh hb-buffer-serialize.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-debug.hh hb-dsalgs.hh hb-face.cc hb-face.hh hb-font.cc \
+       hb-font.hh hb-iter.hh hb-kern.hh hb-machinery.hh hb-map.cc \
+       hb-map.hh hb-mutex.hh hb-null.hh hb-object.hh hb-open-file.hh \
+       hb-open-type.hh hb-ot-cff-common.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-map.cc hb-ot-map-private.hh hb-ot-math.cc \
-       hb-ot-math-table.hh hb-ot-shape.cc \
-       hb-ot-shape-complex-arabic.cc \
-       hb-ot-shape-complex-arabic-fallback.hh \
-       hb-ot-shape-complex-arabic-private.hh \
+       hb-ot-color.cc 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 \
+       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-name-language.cc 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-shape-complex-arabic-fallback.hh \
        hb-ot-shape-complex-arabic-table.hh \
        hb-ot-shape-complex-arabic-win1256.hh \
+       hb-ot-shape-complex-arabic.cc hb-ot-shape-complex-arabic.hh \
        hb-ot-shape-complex-default.cc hb-ot-shape-complex-hangul.cc \
-       hb-ot-shape-complex-hebrew.cc hb-ot-shape-complex-indic.cc \
-       hb-ot-shape-complex-indic-private.hh \
+       hb-ot-shape-complex-hebrew.cc \
        hb-ot-shape-complex-indic-table.cc \
-       hb-ot-shape-complex-khmer-private.hh \
-       hb-ot-shape-complex-khmer.cc \
-       hb-ot-shape-complex-myanmar-private.hh \
-       hb-ot-shape-complex-myanmar.cc hb-ot-shape-complex-thai.cc \
-       hb-ot-shape-complex-tibetan.cc hb-ot-shape-complex-use.cc \
-       hb-ot-shape-complex-use-private.hh \
-       hb-ot-shape-complex-use-table.cc \
-       hb-ot-shape-complex-private.hh \
-       hb-ot-shape-normalize-private.hh hb-ot-shape-normalize.cc \
-       hb-ot-shape-fallback-private.hh hb-ot-shape-fallback.cc \
-       hb-ot-shape-private.hh hb-ot-var.cc hb-ot-var-avar-table.hh \
-       hb-ot-var-fvar-table.hh hb-ot-var-hvar-table.hh \
-       hb-ot-var-mvar-table.hh hb-ot-shape-complex-indic-machine.hh \
+       hb-ot-shape-complex-indic.cc hb-ot-shape-complex-indic.hh \
+       hb-ot-shape-complex-khmer.cc hb-ot-shape-complex-khmer.hh \
+       hb-ot-shape-complex-myanmar.cc hb-ot-shape-complex-myanmar.hh \
+       hb-ot-shape-complex-thai.cc hb-ot-shape-complex-use-table.cc \
+       hb-ot-shape-complex-use.cc hb-ot-shape-complex-use.hh \
+       hb-ot-shape-complex-vowel-constraints.cc \
+       hb-ot-shape-complex-vowel-constraints.hh \
+       hb-ot-shape-complex.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-fvar-table.hh \
+       hb-ot-var-hvar-table.hh hb-ot-var-mvar-table.hh hb-ot-var.cc \
+       hb-ot-vorg-table.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-unicode-emoji-table.hh \
+       hb-unicode.cc hb-unicode.hh hb-utf.hh hb-vector.hh \
+       hb-warning.cc hb.hh hb-buffer-deserialize-json.hh \
+       hb-buffer-deserialize-text.hh \
+       hb-ot-shape-complex-indic-machine.hh \
        hb-ot-shape-complex-khmer-machine.hh \
        hb-ot-shape-complex-myanmar-machine.hh \
        hb-ot-shape-complex-use-machine.hh hb-fallback-shape.cc \
        hb-glib.cc hb-ft.cc hb-graphite2.cc hb-uniscribe.cc \
-       hb-directwrite.cc hb-coretext.cc hb-ucdn.cc hb-icu.cc hb.h \
-       hb-blob.h hb-buffer.h hb-common.h hb-deprecated.h hb-face.h \
-       hb-font.h hb-map.h hb-set.h hb-shape.h hb-shape-plan.h \
-       hb-unicode.h hb-version.h hb-ot.h hb-ot-font.h hb-ot-layout.h \
-       hb-ot-math.h hb-ot-shape.h hb-ot-tag.h hb-ot-var.h hb-glib.h \
-       hb-ft.h hb-graphite2.h hb-uniscribe.h hb-directwrite.h \
-       hb-coretext.h hb-icu.h
-am__objects_42 = libharfbuzz_la-hb-blob.lo \
+       hb-directwrite.cc hb-coretext.cc hb-ucdn.cc hb-icu.cc \
+       hb-aat-layout.h hb-aat.h hb-blob.h hb-buffer.h hb-common.h \
+       hb-deprecated.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-name.h hb-ot-shape.h hb-ot-var.h hb-ot.h hb-set.h \
+       hb-shape-plan.h hb-shape.h hb-unicode.h hb-version.h hb.h \
+       hb-glib.h hb-ft.h hb-graphite2.h hb-uniscribe.h \
+       hb-directwrite.h hb-coretext.h hb-icu.h
+am__objects_7 = libharfbuzz_la-hb-aat-layout.lo \
+       libharfbuzz_la-hb-aat-map.lo libharfbuzz_la-hb-blob.lo \
        libharfbuzz_la-hb-buffer-serialize.lo \
        libharfbuzz_la-hb-buffer.lo libharfbuzz_la-hb-common.lo \
        libharfbuzz_la-hb-face.lo libharfbuzz_la-hb-font.lo \
-       libharfbuzz_la-hb-map.lo libharfbuzz_la-hb-ot-tag.lo \
-       libharfbuzz_la-hb-set.lo libharfbuzz_la-hb-shape.lo \
-       libharfbuzz_la-hb-shape-plan.lo libharfbuzz_la-hb-shaper.lo \
-       libharfbuzz_la-hb-static.lo libharfbuzz_la-hb-unicode.lo \
-       libharfbuzz_la-hb-warning.lo $(am__objects_1)
-am__objects_43 = libharfbuzz_la-hb-aat-layout.lo \
+       libharfbuzz_la-hb-map.lo libharfbuzz_la-hb-ot-cff1-table.lo \
+       libharfbuzz_la-hb-ot-cff2-table.lo \
+       libharfbuzz_la-hb-ot-color.lo libharfbuzz_la-hb-ot-face.lo \
        libharfbuzz_la-hb-ot-font.lo libharfbuzz_la-hb-ot-layout.lo \
-       libharfbuzz_la-hb-ot-color.lo libharfbuzz_la-hb-ot-map.lo \
-       libharfbuzz_la-hb-ot-math.lo libharfbuzz_la-hb-ot-shape.lo \
+       libharfbuzz_la-hb-ot-map.lo libharfbuzz_la-hb-ot-math.lo \
+       libharfbuzz_la-hb-ot-name-language.lo \
+       libharfbuzz_la-hb-ot-name.lo \
        libharfbuzz_la-hb-ot-shape-complex-arabic.lo \
        libharfbuzz_la-hb-ot-shape-complex-default.lo \
        libharfbuzz_la-hb-ot-shape-complex-hangul.lo \
        libharfbuzz_la-hb-ot-shape-complex-hebrew.lo \
-       libharfbuzz_la-hb-ot-shape-complex-indic.lo \
        libharfbuzz_la-hb-ot-shape-complex-indic-table.lo \
+       libharfbuzz_la-hb-ot-shape-complex-indic.lo \
        libharfbuzz_la-hb-ot-shape-complex-khmer.lo \
        libharfbuzz_la-hb-ot-shape-complex-myanmar.lo \
        libharfbuzz_la-hb-ot-shape-complex-thai.lo \
-       libharfbuzz_la-hb-ot-shape-complex-tibetan.lo \
-       libharfbuzz_la-hb-ot-shape-complex-use.lo \
        libharfbuzz_la-hb-ot-shape-complex-use-table.lo \
-       libharfbuzz_la-hb-ot-shape-normalize.lo \
+       libharfbuzz_la-hb-ot-shape-complex-use.lo \
+       libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo \
        libharfbuzz_la-hb-ot-shape-fallback.lo \
-       libharfbuzz_la-hb-ot-var.lo $(am__objects_1)
-@HAVE_OT_TRUE@am__objects_44 = $(am__objects_43) $(am__objects_3)
-am__objects_45 = libharfbuzz_la-hb-fallback-shape.lo $(am__objects_1)
-@HAVE_FALLBACK_TRUE@am__objects_46 = $(am__objects_45)
-am__objects_47 = libharfbuzz_la-hb-glib.lo
-@HAVE_GLIB_TRUE@am__objects_48 = $(am__objects_47)
-am__objects_49 = libharfbuzz_la-hb-ft.lo
-@HAVE_FREETYPE_TRUE@am__objects_50 = $(am__objects_49)
-am__objects_51 = libharfbuzz_la-hb-graphite2.lo
-@HAVE_GRAPHITE2_TRUE@am__objects_52 = $(am__objects_51)
-am__objects_53 = libharfbuzz_la-hb-uniscribe.lo
-@HAVE_UNISCRIBE_TRUE@am__objects_54 = $(am__objects_53)
-am__objects_55 = libharfbuzz_la-hb-directwrite.lo
-@HAVE_DIRECTWRITE_TRUE@am__objects_56 = $(am__objects_55)
-am__objects_57 = libharfbuzz_la-hb-coretext.lo
-@HAVE_CORETEXT_TRUE@am__objects_58 = $(am__objects_57)
-am__objects_59 = libharfbuzz_la-hb-ucdn.lo
-@HAVE_UCDN_TRUE@am__objects_60 = $(am__objects_59)
-am__objects_61 = libharfbuzz_la-hb-icu.lo
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__objects_62 =  \
-@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__objects_61)
-am__objects_63 = $(am__objects_42) $(am__objects_3) $(am__objects_44) \
-       $(am__objects_46) $(am__objects_48) $(am__objects_50) \
-       $(am__objects_52) $(am__objects_54) $(am__objects_56) \
-       $(am__objects_58) $(am__objects_60) $(am__objects_62)
-am_libharfbuzz_la_OBJECTS = $(am__objects_63) $(am__objects_33)
+       libharfbuzz_la-hb-ot-shape-normalize.lo \
+       libharfbuzz_la-hb-ot-shape.lo libharfbuzz_la-hb-ot-tag.lo \
+       libharfbuzz_la-hb-ot-var.lo libharfbuzz_la-hb-set.lo \
+       libharfbuzz_la-hb-shape-plan.lo libharfbuzz_la-hb-shape.lo \
+       libharfbuzz_la-hb-shaper.lo libharfbuzz_la-hb-static.lo \
+       libharfbuzz_la-hb-unicode.lo libharfbuzz_la-hb-warning.lo \
+       $(am__objects_5)
+am__objects_8 = $(am__objects_5)
+am__objects_9 = libharfbuzz_la-hb-fallback-shape.lo $(am__objects_5)
+@HAVE_FALLBACK_TRUE@am__objects_10 = $(am__objects_9)
+am__objects_11 = libharfbuzz_la-hb-glib.lo
+@HAVE_GLIB_TRUE@am__objects_12 = $(am__objects_11)
+am__objects_13 = libharfbuzz_la-hb-ft.lo
+@HAVE_FREETYPE_TRUE@am__objects_14 = $(am__objects_13)
+am__objects_15 = libharfbuzz_la-hb-graphite2.lo
+@HAVE_GRAPHITE2_TRUE@am__objects_16 = $(am__objects_15)
+am__objects_17 = libharfbuzz_la-hb-uniscribe.lo
+@HAVE_UNISCRIBE_TRUE@am__objects_18 = $(am__objects_17)
+am__objects_19 = libharfbuzz_la-hb-directwrite.lo
+@HAVE_DIRECTWRITE_TRUE@am__objects_20 = $(am__objects_19)
+am__objects_21 = libharfbuzz_la-hb-coretext.lo
+@HAVE_CORETEXT_TRUE@am__objects_22 = $(am__objects_21)
+am__objects_23 = libharfbuzz_la-hb-ucdn.lo
+@HAVE_UCDN_TRUE@am__objects_24 = $(am__objects_23)
+am__objects_25 = libharfbuzz_la-hb-icu.lo
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__objects_26 =  \
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__objects_25)
+am__objects_27 = $(am__objects_7) $(am__objects_8) $(am__objects_10) \
+       $(am__objects_12) $(am__objects_14) $(am__objects_16) \
+       $(am__objects_18) $(am__objects_20) $(am__objects_22) \
+       $(am__objects_24) $(am__objects_26)
+@HAVE_GLIB_TRUE@am__objects_28 = $(am__objects_5)
+@HAVE_FREETYPE_TRUE@am__objects_29 = $(am__objects_5)
+@HAVE_GRAPHITE2_TRUE@am__objects_30 = $(am__objects_5)
+@HAVE_UNISCRIBE_TRUE@am__objects_31 = $(am__objects_5)
+@HAVE_DIRECTWRITE_TRUE@am__objects_32 = $(am__objects_5)
+@HAVE_CORETEXT_TRUE@am__objects_33 = $(am__objects_5)
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@am__objects_34 =  \
+@HAVE_ICU_BUILTIN_TRUE@@HAVE_ICU_TRUE@ $(am__objects_5)
+am__objects_35 = $(am__objects_8) $(am__objects_28) $(am__objects_29) \
+       $(am__objects_30) $(am__objects_31) $(am__objects_32) \
+       $(am__objects_33) $(am__objects_34)
+am_libharfbuzz_la_OBJECTS = $(am__objects_27) $(am__objects_35)
 libharfbuzz_la_OBJECTS = $(am_libharfbuzz_la_OBJECTS)
 am__EXEEXT_1 =
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am__EXEEXT_2 =  \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       dump-emoji$(EXEEXT)
+am__EXEEXT_2 = test-iter$(EXEEXT) test-ot-tag$(EXEEXT) \
+       test-unicode-ranges$(EXEEXT)
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am__EXEEXT_3 = test-ot-color$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
-am__dump_emoji_SOURCES_DIST = dump-emoji.cc
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am_dump_emoji_OBJECTS = dump_emoji-dump-emoji.$(OBJEXT)
-dump_emoji_OBJECTS = $(am_dump_emoji_OBJECTS)
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@dump_emoji_DEPENDENCIES =  \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       libharfbuzz.la \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_11) \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1) \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1) \
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1)
-am_dump_fon_OBJECTS = dump_fon-dump-fon.$(OBJEXT)
-dump_fon_OBJECTS = $(am_dump_fon_OBJECTS)
-dump_fon_DEPENDENCIES = libharfbuzz.la $(am__DEPENDENCIES_11)
 am_dump_indic_data_OBJECTS =  \
        dump_indic_data-dump-indic-data.$(OBJEXT) \
        dump_indic_data-hb-ot-shape-complex-indic-table.$(OBJEXT)
@@ -609,17 +460,35 @@ am_test_buffer_serialize_OBJECTS =  \
 test_buffer_serialize_OBJECTS = $(am_test_buffer_serialize_OBJECTS)
 test_buffer_serialize_DEPENDENCIES = libharfbuzz.la \
        $(am__DEPENDENCIES_11)
+am_test_iter_OBJECTS = test_iter-test-iter.$(OBJEXT) \
+       test_iter-hb-static.$(OBJEXT)
+test_iter_OBJECTS = $(am_test_iter_OBJECTS)
+am__DEPENDENCIES_12 = libharfbuzz.la $(am__DEPENDENCIES_11)
+test_iter_DEPENDENCIES = $(am__DEPENDENCIES_12)
+am_test_name_table_OBJECTS =  \
+       test_name_table-test-name-table.$(OBJEXT)
+test_name_table_OBJECTS = $(am_test_name_table_OBJECTS)
+test_name_table_DEPENDENCIES = libharfbuzz.la $(am__DEPENDENCIES_11)
+am__test_ot_color_SOURCES_DIST = test-ot-color.cc
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@am_test_ot_color_OBJECTS = test_ot_color-test-ot-color.$(OBJEXT)
+test_ot_color_OBJECTS = $(am_test_ot_color_OBJECTS)
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@test_ot_color_DEPENDENCIES =  \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       libharfbuzz.la \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_11) \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1) \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1) \
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@       $(am__DEPENDENCIES_1)
 am_test_ot_tag_OBJECTS = test_ot_tag-hb-ot-tag.$(OBJEXT)
 test_ot_tag_OBJECTS = $(am_test_ot_tag_OBJECTS)
-test_ot_tag_DEPENDENCIES = libharfbuzz.la $(am__DEPENDENCIES_11)
+test_ot_tag_DEPENDENCIES = $(am__DEPENDENCIES_12)
 am_test_size_params_OBJECTS =  \
        test_size_params-test-size-params.$(OBJEXT)
 test_size_params_OBJECTS = $(am_test_size_params_OBJECTS)
 test_size_params_DEPENDENCIES = libharfbuzz.la $(am__DEPENDENCIES_11)
-am_test_unicode_ranges_OBJECTS = test-unicode-ranges.$(OBJEXT)
+am_test_unicode_ranges_OBJECTS =  \
+       test_unicode_ranges-test-unicode-ranges.$(OBJEXT)
 test_unicode_ranges_OBJECTS = $(am_test_unicode_ranges_OBJECTS)
-test_unicode_ranges_DEPENDENCIES = libharfbuzz.la \
-       $(am__DEPENDENCIES_11)
+test_unicode_ranges_DEPENDENCIES = $(am__DEPENDENCIES_12)
 am_test_would_substitute_OBJECTS =  \
        test_would_substitute-test-would-substitute.$(OBJEXT)
 test_would_substitute_OBJECTS = $(am_test_would_substitute_OBJECTS)
@@ -680,31 +549,27 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(libharfbuzz_fuzzing_la_SOURCES) \
-       $(libharfbuzz_gobject_la_SOURCES) \
+SOURCES = $(libharfbuzz_gobject_la_SOURCES) \
        $(nodist_libharfbuzz_gobject_la_SOURCES) \
-       $(libharfbuzz_icu_la_SOURCES) \
-       $(libharfbuzz_subset_fuzzing_la_SOURCES) \
-       $(libharfbuzz_subset_la_SOURCES) $(libharfbuzz_la_SOURCES) \
-       $(dump_emoji_SOURCES) $(dump_fon_SOURCES) \
-       $(dump_indic_data_SOURCES) $(dump_khmer_data_SOURCES) \
-       $(dump_myanmar_data_SOURCES) $(dump_use_data_SOURCES) \
-       $(main_SOURCES) $(test_SOURCES) \
-       $(test_buffer_serialize_SOURCES) $(test_ot_tag_SOURCES) \
-       $(test_size_params_SOURCES) $(test_unicode_ranges_SOURCES) \
+       $(libharfbuzz_icu_la_SOURCES) $(libharfbuzz_subset_la_SOURCES) \
+       $(libharfbuzz_la_SOURCES) $(dump_indic_data_SOURCES) \
+       $(dump_khmer_data_SOURCES) $(dump_myanmar_data_SOURCES) \
+       $(dump_use_data_SOURCES) $(main_SOURCES) $(test_SOURCES) \
+       $(test_buffer_serialize_SOURCES) $(test_iter_SOURCES) \
+       $(test_name_table_SOURCES) $(test_ot_color_SOURCES) \
+       $(test_ot_tag_SOURCES) $(test_size_params_SOURCES) \
+       $(test_unicode_ranges_SOURCES) \
        $(test_would_substitute_SOURCES)
-DIST_SOURCES = $(am__libharfbuzz_fuzzing_la_SOURCES_DIST) \
-       $(am__libharfbuzz_gobject_la_SOURCES_DIST) \
+DIST_SOURCES = $(am__libharfbuzz_gobject_la_SOURCES_DIST) \
        $(am__libharfbuzz_icu_la_SOURCES_DIST) \
-       $(libharfbuzz_subset_fuzzing_la_SOURCES) \
        $(libharfbuzz_subset_la_SOURCES) \
-       $(am__libharfbuzz_la_SOURCES_DIST) \
-       $(am__dump_emoji_SOURCES_DIST) $(dump_fon_SOURCES) \
-       $(dump_indic_data_SOURCES) $(dump_khmer_data_SOURCES) \
-       $(dump_myanmar_data_SOURCES) $(dump_use_data_SOURCES) \
-       $(main_SOURCES) $(test_SOURCES) \
-       $(test_buffer_serialize_SOURCES) $(test_ot_tag_SOURCES) \
-       $(test_size_params_SOURCES) $(test_unicode_ranges_SOURCES) \
+       $(am__libharfbuzz_la_SOURCES_DIST) $(dump_indic_data_SOURCES) \
+       $(dump_khmer_data_SOURCES) $(dump_myanmar_data_SOURCES) \
+       $(dump_use_data_SOURCES) $(main_SOURCES) $(test_SOURCES) \
+       $(test_buffer_serialize_SOURCES) $(test_iter_SOURCES) \
+       $(test_name_table_SOURCES) $(am__test_ot_color_SOURCES_DIST) \
+       $(test_ot_tag_SOURCES) $(test_size_params_SOURCES) \
+       $(test_unicode_ranges_SOURCES) \
        $(test_would_substitute_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
        ctags-recursive dvi-recursive html-recursive info-recursive \
@@ -720,14 +585,14 @@ am__can_run_installinfo = \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
 DATA = $(cmake_DATA) $(gir_DATA) $(pkgconfig_DATA) $(typelib_DATA)
-am__pkginclude_HEADERS_DIST = hb.h hb-blob.h hb-buffer.h hb-common.h \
-       hb-deprecated.h hb-face.h hb-font.h hb-map.h hb-set.h \
-       hb-shape.h hb-shape-plan.h hb-unicode.h hb-version.h hb-ot.h \
-       hb-ot-font.h hb-ot-layout.h hb-ot-math.h hb-ot-shape.h \
-       hb-ot-tag.h hb-ot-var.h hb-glib.h hb-ft.h hb-graphite2.h \
-       hb-uniscribe.h hb-directwrite.h hb-coretext.h hb-icu.h \
-       hb-subset.h hb-subset-glyf.hh hb-subset-plan.hh \
-       hb-subset-private.hh hb-gobject.h hb-gobject-structs.h
+am__pkginclude_HEADERS_DIST = hb-aat-layout.h hb-aat.h hb-blob.h \
+       hb-buffer.h hb-common.h hb-deprecated.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-name.h hb-ot-shape.h \
+       hb-ot-var.h hb-ot.h hb-set.h hb-shape-plan.h hb-shape.h \
+       hb-unicode.h hb-version.h hb.h hb-glib.h hb-ft.h \
+       hb-graphite2.h hb-uniscribe.h hb-directwrite.h hb-coretext.h \
+       hb-icu.h hb-subset.h hb-gobject.h hb-gobject-structs.h
 HEADERS = $(nodist_pkginclude_HEADERS) $(pkginclude_HEADERS)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
   distclean-recursive maintainer-clean-recursive
@@ -912,11 +777,11 @@ am__set_TESTS_bases = \
   bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
   bases=`echo $$bases`
 RECHECK_LOGS = $(TEST_LOGS)
-@WITH_LIBSTDCXX_FALSE@am__EXEEXT_3 = check-libstdc++.sh \
+@WITH_LIBSTDCXX_FALSE@am__EXEEXT_4 = check-libstdc++.sh \
 @WITH_LIBSTDCXX_FALSE@ $(am__EXEEXT_1)
-am__EXEEXT_4 = check-c-linkage-decls.sh check-externs.sh \
+am__EXEEXT_5 = check-c-linkage-decls.sh check-externs.sh \
        check-header-guards.sh check-includes.sh check-static-inits.sh \
-       check-symbols.sh $(am__EXEEXT_1) $(am__EXEEXT_3)
+       check-symbols.sh $(am__EXEEXT_1) $(am__EXEEXT_4)
 TEST_SUITE_LOG = test-suite.log
 TEST_EXTENSIONS = @EXEEXT@ .test
 LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
@@ -1083,6 +948,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -1152,87 +1019,189 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 NULL = 
-SUBDIRS = $(am__append_32)
+SUBDIRS = $(am__append_30)
 DIST_SUBDIRS = hb-ucdn
-BUILT_SOURCES = hb-version.h $(am__append_47) $(RAGEL_GENERATED)
+BUILT_SOURCES = hb-version.h $(am__append_45) $(RAGEL_GENERATED)
 EXTRA_DIST = hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in \
        harfbuzz-subset.pc.in harfbuzz-icu.pc.in \
        harfbuzz-gobject.pc.in hb-gobject-enums.cc.tmpl \
        hb-gobject-enums.h.tmpl $(NULL) $(GENERATORS) \
-       $(HB_BASE_RAGEL_sources) $(HB_OT_RAGEL_sources) $(NULL)
-CLEANFILES = libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la \
-       $(pkgconfig_DATA) $(DEF_FILES) $(am__append_52)
-DISTCLEANFILES = $(am__append_48)
+       $(HB_BASE_RAGEL_sources) $(NULL)
+CLEANFILES = $(pkgconfig_DATA) $(DEF_FILES) $(am__append_50)
+DISTCLEANFILES = $(am__append_46)
 MAINTAINERCLEANFILES = 
 DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
 lib_LTLIBRARIES = libharfbuzz.la libharfbuzz-subset.la \
-       $(am__append_40) $(am__append_43)
+       $(am__append_38) $(am__append_41)
 HB_BASE_sources = \
-       hb-atomic-private.hh \
-       hb-blob-private.hh \
+       hb-aat-fdsc-table.hh \
+       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-lcar-table.hh \
+       hb-aat-layout-morx-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-array.hh \
+       hb-atomic.hh \
        hb-blob.cc \
-       hb-buffer-private.hh \
+       hb-blob.hh \
        hb-buffer-serialize.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-debug.hh \
        hb-dsalgs.hh \
-       hb-face-private.hh \
        hb-face.cc \
-       hb-font-private.hh \
+       hb-face.hh \
        hb-font.cc \
-       hb-map-private.hh \
+       hb-font.hh \
+       hb-iter.hh \
+       hb-kern.hh \
+       hb-machinery.hh \
        hb-map.cc \
-       hb-mutex-private.hh \
-       hb-object-private.hh \
-       hb-open-file-private.hh \
-       hb-open-type-private.hh \
-       hb-ot-color-cbdt-table.hh \
+       hb-map.hh \
+       hb-mutex.hh \
+       hb-null.hh \
+       hb-object.hh \
+       hb-open-file.hh \
+       hb-open-type.hh \
+       hb-ot-cff-common.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.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 \
+       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-name-language.cc \
+       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-shape-complex-arabic-fallback.hh \
+       hb-ot-shape-complex-arabic-table.hh \
+       hb-ot-shape-complex-arabic-win1256.hh \
+       hb-ot-shape-complex-arabic.cc \
+       hb-ot-shape-complex-arabic.hh \
+       hb-ot-shape-complex-default.cc \
+       hb-ot-shape-complex-hangul.cc \
+       hb-ot-shape-complex-hebrew.cc \
+       hb-ot-shape-complex-indic-table.cc \
+       hb-ot-shape-complex-indic.cc \
+       hb-ot-shape-complex-indic.hh \
+       hb-ot-shape-complex-khmer.cc \
+       hb-ot-shape-complex-khmer.hh \
+       hb-ot-shape-complex-myanmar.cc \
+       hb-ot-shape-complex-myanmar.hh \
+       hb-ot-shape-complex-thai.cc \
+       hb-ot-shape-complex-use-table.cc \
+       hb-ot-shape-complex-use.cc \
+       hb-ot-shape-complex-use.hh \
+       hb-ot-shape-complex-vowel-constraints.cc \
+       hb-ot-shape-complex-vowel-constraints.hh \
+       hb-ot-shape-complex.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-private.hh \
-       hb-set-digest-private.hh \
-       hb-set-private.hh \
+       hb-ot-var-avar-table.hh \
+       hb-ot-var-fvar-table.hh \
+       hb-ot-var-hvar-table.hh \
+       hb-ot-var-mvar-table.hh \
+       hb-ot-var.cc \
+       hb-ot-vorg-table.hh \
+       hb-set-digest.hh \
        hb-set.cc \
-       hb-shape.cc \
-       hb-shape-plan-private.hh \
+       hb-set.hh \
        hb-shape-plan.cc \
+       hb-shape-plan.hh \
+       hb-shape.cc \
+       hb-shaper-impl.hh \
        hb-shaper-list.hh \
-       hb-shaper-impl-private.hh \
-       hb-shaper-private.hh \
        hb-shaper.cc \
+       hb-shaper.hh \
        hb-static.cc \
        hb-string-array.hh \
-       hb-unicode-private.hh \
+       hb-unicode-emoji-table.hh \
        hb-unicode.cc \
-       hb-utf-private.hh \
+       hb-unicode.hh \
+       hb-utf.hh \
+       hb-vector.hh \
        hb-warning.cc \
+       hb.hh \
        $(NULL)
 
 HB_BASE_RAGEL_GENERATED_sources = \
        hb-buffer-deserialize-json.hh \
        hb-buffer-deserialize-text.hh \
+       hb-ot-shape-complex-indic-machine.hh \
+       hb-ot-shape-complex-khmer-machine.hh \
+       hb-ot-shape-complex-myanmar-machine.hh \
+       hb-ot-shape-complex-use-machine.hh \
        $(NULL)
 
 HB_BASE_RAGEL_sources = \
        hb-buffer-deserialize-json.rl \
        hb-buffer-deserialize-text.rl \
+       hb-ot-shape-complex-indic-machine.rl \
+       hb-ot-shape-complex-khmer-machine.rl \
+       hb-ot-shape-complex-myanmar-machine.rl \
+       hb-ot-shape-complex-use-machine.rl \
        $(NULL)
 
 HB_BASE_headers = \
-       hb.h \
+       hb-aat-layout.h \
+       hb-aat.h \
        hb-blob.h \
        hb-buffer.h \
        hb-common.h \
@@ -1240,107 +1209,27 @@ HB_BASE_headers = \
        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-name.h \
+       hb-ot-shape.h \
+       hb-ot-var.h \
+       hb-ot.h \
        hb-set.h \
-       hb-shape.h \
        hb-shape-plan.h \
+       hb-shape.h \
        hb-unicode.h \
        hb-version.h \
+       hb.h \
        $(NULL)
 
 HB_FALLBACK_sources = \
        hb-fallback-shape.cc    \
        $(NULL)
 
-HB_OT_sources = \
-       hb-aat-layout.cc \
-       hb-aat-layout-common-private.hh \
-       hb-aat-layout-ankr-table.hh \
-       hb-aat-layout-bsln-table.hh \
-       hb-aat-layout-feat-table.hh \
-       hb-aat-layout-kerx-table.hh \
-       hb-aat-layout-morx-table.hh \
-       hb-aat-layout-trak-table.hh \
-       hb-aat-layout-private.hh \
-       hb-aat-fmtx-table.hh \
-       hb-aat-gcid-table.hh \
-       hb-aat-ltag-table.hh \
-       hb-ot-font.cc \
-       hb-ot-layout.cc \
-       hb-ot-layout-base-table.hh \
-       hb-ot-layout-common-private.hh \
-       hb-ot-layout-gdef-table.hh \
-       hb-ot-layout-gpos-table.hh \
-       hb-ot-layout-gsubgpos-private.hh \
-       hb-ot-layout-gsub-table.hh \
-       hb-ot-layout-jstf-table.hh \
-       hb-ot-layout-private.hh \
-       hb-ot-color.cc \
-       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-map.cc \
-       hb-ot-map-private.hh \
-       hb-ot-math.cc \
-       hb-ot-math-table.hh \
-       hb-ot-shape.cc \
-       hb-ot-shape-complex-arabic.cc \
-       hb-ot-shape-complex-arabic-fallback.hh \
-       hb-ot-shape-complex-arabic-private.hh \
-       hb-ot-shape-complex-arabic-table.hh \
-       hb-ot-shape-complex-arabic-win1256.hh \
-       hb-ot-shape-complex-default.cc \
-       hb-ot-shape-complex-hangul.cc \
-       hb-ot-shape-complex-hebrew.cc \
-       hb-ot-shape-complex-indic.cc \
-       hb-ot-shape-complex-indic-private.hh \
-       hb-ot-shape-complex-indic-table.cc \
-       hb-ot-shape-complex-khmer-private.hh \
-       hb-ot-shape-complex-khmer.cc \
-       hb-ot-shape-complex-myanmar-private.hh \
-       hb-ot-shape-complex-myanmar.cc \
-       hb-ot-shape-complex-thai.cc \
-       hb-ot-shape-complex-tibetan.cc \
-       hb-ot-shape-complex-use.cc \
-       hb-ot-shape-complex-use-private.hh \
-       hb-ot-shape-complex-use-table.cc \
-       hb-ot-shape-complex-private.hh \
-       hb-ot-shape-normalize-private.hh \
-       hb-ot-shape-normalize.cc \
-       hb-ot-shape-fallback-private.hh \
-       hb-ot-shape-fallback.cc \
-       hb-ot-shape-private.hh \
-       hb-ot-var.cc \
-       hb-ot-var-avar-table.hh \
-       hb-ot-var-fvar-table.hh \
-       hb-ot-var-hvar-table.hh \
-       hb-ot-var-mvar-table.hh \
-       $(NULL)
-
-HB_OT_RAGEL_GENERATED_sources = \
-       hb-ot-shape-complex-indic-machine.hh \
-       hb-ot-shape-complex-khmer-machine.hh \
-       hb-ot-shape-complex-myanmar-machine.hh \
-       hb-ot-shape-complex-use-machine.hh \
-       $(NULL)
-
-HB_OT_RAGEL_sources = \
-       hb-ot-shape-complex-indic-machine.rl \
-       hb-ot-shape-complex-khmer-machine.rl \
-       hb-ot-shape-complex-myanmar-machine.rl \
-       hb-ot-shape-complex-use-machine.rl \
-       $(NULL)
-
-HB_OT_headers = \
-       hb-ot.h \
-       hb-ot-font.h \
-       hb-ot-layout.h \
-       hb-ot-math.h \
-       hb-ot-shape.h \
-       hb-ot-tag.h \
-       hb-ot-var.h \
-       $(NULL)
-
 
 # Optional Sources and Headers with external deps
 HB_FT_sources = hb-ft.cc
@@ -1367,18 +1256,30 @@ HB_ICU_headers = hb-icu.h
 
 # Sources for libharfbuzz-subset
 HB_SUBSET_sources = \
+       hb-ot-cff1-table.cc \
+       hb-ot-cff2-table.cc \
        hb-static.cc \
-       hb-subset.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-glyf.cc \
+       hb-subset-glyf.hh \
+       hb-subset-glyf.hh \
        hb-subset-input.cc \
+       hb-subset-input.hh \
        hb-subset-plan.cc \
+       hb-subset-plan.hh \
+       hb-subset-plan.hh \
+       hb-subset.cc \
+       hb-subset.hh \
+       hb-subset.hh \
        $(NULL)
 
 HB_SUBSET_headers = \
        hb-subset.h \
-       hb-subset-glyf.hh \
-       hb-subset-plan.hh \
-       hb-subset-private.hh \
        $(NULL)
 
 HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
@@ -1389,24 +1290,23 @@ 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)
-HBCFLAGS = $(am__append_4) $(am__append_6) $(am__append_11) \
-       $(am__append_15) $(am__append_20) $(am__append_24) \
-       $(am__append_28) $(am__append_33) $(am__append_36)
+HBCFLAGS = $(am__append_2) $(am__append_4) $(am__append_9) \
+       $(am__append_13) $(am__append_18) $(am__append_22) \
+       $(am__append_26) $(am__append_31) $(am__append_34)
 
 # Put the library together
-HBLIBS = $(am__append_7) $(am__append_12) $(am__append_16) \
-       $(am__append_34) $(HBNONPCLIBS) $(am__append_37)
-HBNONPCLIBS = $(am__append_5) $(am__append_21) $(am__append_25) \
-       $(am__append_29)
-HBDEPS = $(am__append_8) $(am__append_17)
+HBLIBS = $(am__append_5) $(am__append_10) $(am__append_14) \
+       $(am__append_32) $(HBNONPCLIBS) $(am__append_35)
+HBNONPCLIBS = $(am__append_3) $(am__append_19) $(am__append_23) \
+       $(am__append_27)
+HBDEPS = $(am__append_6) $(am__append_15)
 HBSOURCES = $(HB_BASE_sources) $(HB_BASE_RAGEL_GENERATED_sources) \
-       $(am__append_1) $(am__append_3) $(am__append_9) \
-       $(am__append_13) $(am__append_18) $(am__append_22) \
-       $(am__append_26) $(am__append_30) $(am__append_35) \
-       $(am__append_38)
-HBHEADERS = $(HB_BASE_headers) $(am__append_2) $(am__append_10) \
-       $(am__append_14) $(am__append_19) $(am__append_23) \
-       $(am__append_27) $(am__append_31) $(am__append_39)
+       $(am__append_1) $(am__append_7) $(am__append_11) \
+       $(am__append_16) $(am__append_20) $(am__append_24) \
+       $(am__append_28) $(am__append_33) $(am__append_36)
+HBHEADERS = $(HB_BASE_headers) $(am__append_8) $(am__append_12) \
+       $(am__append_17) $(am__append_21) $(am__append_25) \
+       $(am__append_29) $(am__append_37)
 @OS_WIN32_TRUE@export_symbols = -export-symbols harfbuzz.def
 @OS_WIN32_TRUE@harfbuzz_def_dependency = harfbuzz.def
 @OS_WIN32_TRUE@export_symbols_subset = -export-symbols harfbuzz-subset.def
@@ -1428,11 +1328,11 @@ libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols) $(CODE_COVERAGE_LD
 libharfbuzz_la_LIBADD = $(HBLIBS)
 EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
 pkginclude_HEADERS = $(HBHEADERS) $(HB_SUBSET_headers) \
-       $(am__append_41) $(am__append_44)
-nodist_pkginclude_HEADERS = $(am__append_45)
+       $(am__append_39) $(am__append_42)
+nodist_pkginclude_HEADERS = $(am__append_43)
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = harfbuzz.pc harfbuzz-subset.pc $(am__append_42) \
-       $(am__append_46)
+pkgconfig_DATA = harfbuzz.pc harfbuzz-subset.pc $(am__append_40) \
+       $(am__append_44)
 cmakedir = $(libdir)/cmake/harfbuzz
 cmake_DATA = harfbuzz-config.cmake
 libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
@@ -1440,33 +1340,6 @@ 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)
-FUZZING_CPPFLAGS = \
-       -DHB_NDEBUG \
-       -DHB_MAX_NESTING_LEVEL=3 \
-       -DHB_SANITIZE_MAX_EDITS=3 \
-       -DHB_SANITIZE_MAX_OPS_FACTOR=3 \
-       -DHB_SANITIZE_MAX_OPS_MIN=128 \
-       -DHB_BUFFER_MAX_LEN_FACTOR=3 \
-       -DHB_BUFFER_MAX_LEN_MIN=8 \
-       -DHB_BUFFER_MAX_LEN_DEFAULT=128 \
-       -DHB_BUFFER_MAX_OPS_FACTOR=8 \
-       -DHB_BUFFER_MAX_OPS_MIN=64 \
-       -DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
-       $(NULL)
-
-EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
-libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS)
-libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
-libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
-libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
-libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
-EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
-libharfbuzz_subset_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_subset_fuzzing_la_LDFLAGS)
-libharfbuzz_subset_fuzzing_la_SOURCES = $(libharfbuzz_subset_la_SOURCES)
-libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
-libharfbuzz_subset_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
-libharfbuzz_subset_fuzzing_la_LIBADD = $(libharfbuzz_subset_la_LIBADD)
-EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES)
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS) $(CODE_COVERAGE_CFLAGS)
 @HAVE_ICU_BUILTIN_FALSE@@HAVE_ICU_TRUE@libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu) $(CODE_COVERAGE_LDFLAGS)
@@ -1480,17 +1353,20 @@ EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la
 @HAVE_GOBJECT_TRUE@libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
 @HAVE_GOBJECT_TRUE@EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency)
 DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def \
-       $(am__append_49)
+       harfbuzz-deprecated-symbols.txt $(am__append_47)
 GENERATORS = \
        gen-arabic-table.py \
+       gen-def.py \
+       gen-emoji-table.py \
        gen-indic-table.py \
+       gen-os2-unicode-ranges.py \
+       gen-tag-table.py \
        gen-use-table.py \
-       gen-def.py \
+       gen-vowel-constraints.py \
        $(NULL)
 
 RAGEL_GENERATED = \
        $(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
-       $(patsubst %,$(srcdir)/%,$(HB_OT_RAGEL_GENERATED_sources)) \
        $(NULL)
 
 main_SOURCES = main.cc
@@ -1499,21 +1375,24 @@ main_LDADD = libharfbuzz.la $(HBLIBS)
 test_SOURCES = test.cc
 test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
 test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-test_would_substitute_SOURCES = test-would-substitute.cc
-test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
-test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-test_size_params_SOURCES = test-size-params.cc
-test_size_params_CPPFLAGS = $(HBCFLAGS)
-test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
 test_buffer_serialize_SOURCES = test-buffer-serialize.cc
 test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
 test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
+test_name_table_SOURCES = test-name-table.cc
+test_name_table_CPPFLAGS = $(HBCFLAGS)
+test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
+test_size_params_SOURCES = test-size-params.cc
+test_size_params_CPPFLAGS = $(HBCFLAGS)
+test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
+test_would_substitute_SOURCES = test-would-substitute.cc
+test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@test_ot_color_SOURCES = test-ot-color.cc
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
 dist_check_SCRIPTS = check-c-linkage-decls.sh check-externs.sh \
        check-header-guards.sh check-includes.sh check-static-inits.sh \
-       check-symbols.sh $(NULL) $(am__append_50)
-dump_fon_SOURCES = dump-fon.cc
-dump_fon_CPPFLAGS = $(HBCFLAGS)
-dump_fon_LDADD = libharfbuzz.la $(HBLIBS)
+       check-symbols.sh $(NULL) $(am__append_49)
 dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
 dump_indic_data_CPPFLAGS = $(HBCFLAGS)
 dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
@@ -1526,14 +1405,18 @@ dump_myanmar_data_LDADD = libharfbuzz.la $(HBLIBS)
 dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
 dump_use_data_CPPFLAGS = $(HBCFLAGS)
 dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@dump_emoji_SOURCES = dump-emoji.cc
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@dump_emoji_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@dump_emoji_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
+COMPILED_TESTS = test-iter test-ot-tag test-unicode-ranges
+COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
+COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
+test_iter_SOURCES = test-iter.cc hb-static.cc
+test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_iter_LDADD = $(COMPILED_TESTS_LDADD)
 test_ot_tag_SOURCES = hb-ot-tag.cc
-test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
-test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
+test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
 test_unicode_ranges_SOURCES = test-unicode-ranges.cc
-test_unicode_ranges_LDADD = libharfbuzz.la $(HBLIBS)
+test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
 TESTS_ENVIRONMENT = \
        srcdir="$(srcdir)" \
        MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
@@ -1553,6 +1436,8 @@ TESTS_ENVIRONMENT = \
 @HAVE_INTROSPECTION_TRUE@      -DHB_H_IN \
 @HAVE_INTROSPECTION_TRUE@      -DHB_OT_H \
 @HAVE_INTROSPECTION_TRUE@      -DHB_OT_H_IN \
+@HAVE_INTROSPECTION_TRUE@      -DHB_AAT_H \
+@HAVE_INTROSPECTION_TRUE@      -DHB_AAT_H_IN \
 @HAVE_INTROSPECTION_TRUE@      -DHB_GOBJECT_H \
 @HAVE_INTROSPECTION_TRUE@      -DHB_GOBJECT_H_IN \
 @HAVE_INTROSPECTION_TRUE@      -DHB_EXTERN= \
@@ -1647,18 +1532,12 @@ clean-libLTLIBRARIES:
          rm -f $${locs}; \
        }
 
-libharfbuzz-fuzzing.la: $(libharfbuzz_fuzzing_la_OBJECTS) $(libharfbuzz_fuzzing_la_DEPENDENCIES) $(EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES) 
-       $(AM_V_GEN)$(libharfbuzz_fuzzing_la_LINK)  $(libharfbuzz_fuzzing_la_OBJECTS) $(libharfbuzz_fuzzing_la_LIBADD) $(LIBS)
-
 libharfbuzz-gobject.la: $(libharfbuzz_gobject_la_OBJECTS) $(libharfbuzz_gobject_la_DEPENDENCIES) $(EXTRA_libharfbuzz_gobject_la_DEPENDENCIES) 
        $(AM_V_GEN)$(libharfbuzz_gobject_la_LINK) $(am_libharfbuzz_gobject_la_rpath) $(libharfbuzz_gobject_la_OBJECTS) $(libharfbuzz_gobject_la_LIBADD) $(LIBS)
 
 libharfbuzz-icu.la: $(libharfbuzz_icu_la_OBJECTS) $(libharfbuzz_icu_la_DEPENDENCIES) $(EXTRA_libharfbuzz_icu_la_DEPENDENCIES) 
        $(AM_V_CXXLD)$(libharfbuzz_icu_la_LINK) $(am_libharfbuzz_icu_la_rpath) $(libharfbuzz_icu_la_OBJECTS) $(libharfbuzz_icu_la_LIBADD) $(LIBS)
 
-libharfbuzz-subset-fuzzing.la: $(libharfbuzz_subset_fuzzing_la_OBJECTS) $(libharfbuzz_subset_fuzzing_la_DEPENDENCIES) $(EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES) 
-       $(AM_V_GEN)$(libharfbuzz_subset_fuzzing_la_LINK)  $(libharfbuzz_subset_fuzzing_la_OBJECTS) $(libharfbuzz_subset_fuzzing_la_LIBADD) $(LIBS)
-
 libharfbuzz-subset.la: $(libharfbuzz_subset_la_OBJECTS) $(libharfbuzz_subset_la_DEPENDENCIES) $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES) 
        $(AM_V_CXXLD)$(libharfbuzz_subset_la_LINK) -rpath $(libdir) $(libharfbuzz_subset_la_OBJECTS) $(libharfbuzz_subset_la_LIBADD) $(LIBS)
 
@@ -1748,14 +1627,6 @@ clean-noinstPROGRAMS:
        echo " rm -f" $$list; \
        rm -f $$list
 
-dump-emoji$(EXEEXT): $(dump_emoji_OBJECTS) $(dump_emoji_DEPENDENCIES) $(EXTRA_dump_emoji_DEPENDENCIES) 
-       @rm -f dump-emoji$(EXEEXT)
-       $(AM_V_CXXLD)$(CXXLINK) $(dump_emoji_OBJECTS) $(dump_emoji_LDADD) $(LIBS)
-
-dump-fon$(EXEEXT): $(dump_fon_OBJECTS) $(dump_fon_DEPENDENCIES) $(EXTRA_dump_fon_DEPENDENCIES) 
-       @rm -f dump-fon$(EXEEXT)
-       $(AM_V_CXXLD)$(CXXLINK) $(dump_fon_OBJECTS) $(dump_fon_LDADD) $(LIBS)
-
 dump-indic-data$(EXEEXT): $(dump_indic_data_OBJECTS) $(dump_indic_data_DEPENDENCIES) $(EXTRA_dump_indic_data_DEPENDENCIES) 
        @rm -f dump-indic-data$(EXEEXT)
        $(AM_V_CXXLD)$(CXXLINK) $(dump_indic_data_OBJECTS) $(dump_indic_data_LDADD) $(LIBS)
@@ -1784,6 +1655,18 @@ test-buffer-serialize$(EXEEXT): $(test_buffer_serialize_OBJECTS) $(test_buffer_s
        @rm -f test-buffer-serialize$(EXEEXT)
        $(AM_V_CXXLD)$(CXXLINK) $(test_buffer_serialize_OBJECTS) $(test_buffer_serialize_LDADD) $(LIBS)
 
+test-iter$(EXEEXT): $(test_iter_OBJECTS) $(test_iter_DEPENDENCIES) $(EXTRA_test_iter_DEPENDENCIES) 
+       @rm -f test-iter$(EXEEXT)
+       $(AM_V_CXXLD)$(CXXLINK) $(test_iter_OBJECTS) $(test_iter_LDADD) $(LIBS)
+
+test-name-table$(EXEEXT): $(test_name_table_OBJECTS) $(test_name_table_DEPENDENCIES) $(EXTRA_test_name_table_DEPENDENCIES) 
+       @rm -f test-name-table$(EXEEXT)
+       $(AM_V_CXXLD)$(CXXLINK) $(test_name_table_OBJECTS) $(test_name_table_LDADD) $(LIBS)
+
+test-ot-color$(EXEEXT): $(test_ot_color_OBJECTS) $(test_ot_color_DEPENDENCIES) $(EXTRA_test_ot_color_DEPENDENCIES) 
+       @rm -f test-ot-color$(EXEEXT)
+       $(AM_V_CXXLD)$(CXXLINK) $(test_ot_color_OBJECTS) $(test_ot_color_LDADD) $(LIBS)
+
 test-ot-tag$(EXEEXT): $(test_ot_tag_OBJECTS) $(test_ot_tag_DEPENDENCIES) $(EXTRA_test_ot_tag_DEPENDENCIES) 
        @rm -f test-ot-tag$(EXEEXT)
        $(AM_V_CXXLD)$(CXXLINK) $(test_ot_tag_OBJECTS) $(test_ot_tag_LDADD) $(LIBS)
@@ -1806,8 +1689,6 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_emoji-dump-emoji.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_fon-dump-fon.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_indic_data-dump-indic-data.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_indic_data-hb-ot-shape-complex-indic-table.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_khmer_data-dump-khmer-data.Po@am__quote@
@@ -1816,56 +1697,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_myanmar_data-hb-ot-shape-complex-indic-table.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_use_data-dump-use-data.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump_use_data-hb-ot-shape-complex-use-table.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-aat-layout.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-blob.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer-serialize.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-common.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-coretext.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-directwrite.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-face.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-fallback-shape.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-font.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ft.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-glib.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-graphite2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-icu.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-map.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-color.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-font.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-layout.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-map.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-math.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-fallback.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-normalize.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-tag.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-var.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-set.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape-plan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-shaper.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-static.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-ucdn.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-unicode.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-uniscribe.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_fuzzing_la-hb-warning.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_icu_la-hb-icu.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-aat-layout.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-aat-map.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-blob.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-buffer-serialize.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-buffer.Plo@am__quote@
@@ -1880,11 +1716,16 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-graphite2.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-icu.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-cff1-table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-cff2-table.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-color.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-face.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-font.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-layout.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-map.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-math.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-name-language.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-name.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-arabic.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-default.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-hangul.Plo@am__quote@
@@ -1894,9 +1735,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-khmer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-myanmar.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-thai.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-tibetan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape-normalize.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-ot-shape.Plo@am__quote@
@@ -1911,22 +1752,26 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-unicode.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-uniscribe.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_la-hb-warning.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-static.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-glyf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-input.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-plan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff1-table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff2-table.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-static.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff-common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff2.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-glyf.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-input.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset-plan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libharfbuzz_subset_la-hb-subset.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-test.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-unicode-ranges.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_buffer_serialize-test-buffer-serialize.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_iter-hb-static.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_iter-test-iter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_name_table-test-name-table.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ot_color-test-ot-color.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ot_tag-hb-ot-tag.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_size_params-test-size-params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_would_substitute-test-would-substitute.Po@am__quote@
 
 .cc.o:
@@ -1950,383 +1795,40 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
-libharfbuzz_fuzzing_la-hb-blob.lo: hb-blob.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-blob.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-blob.Tpo -c -o libharfbuzz_fuzzing_la-hb-blob.lo `test -f 'hb-blob.cc' || echo '$(srcdir)/'`hb-blob.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-blob.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-blob.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-blob.cc' object='libharfbuzz_fuzzing_la-hb-blob.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-blob.lo `test -f 'hb-blob.cc' || echo '$(srcdir)/'`hb-blob.cc
-
-libharfbuzz_fuzzing_la-hb-buffer-serialize.lo: hb-buffer-serialize.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-buffer-serialize.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer-serialize.Tpo -c -o libharfbuzz_fuzzing_la-hb-buffer-serialize.lo `test -f 'hb-buffer-serialize.cc' || echo '$(srcdir)/'`hb-buffer-serialize.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer-serialize.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer-serialize.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-buffer-serialize.cc' object='libharfbuzz_fuzzing_la-hb-buffer-serialize.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_gobject_la-hb-gobject-structs.lo: hb-gobject-structs.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_gobject_la-hb-gobject-structs.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Tpo -c -o libharfbuzz_gobject_la-hb-gobject-structs.lo `test -f 'hb-gobject-structs.cc' || echo '$(srcdir)/'`hb-gobject-structs.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Tpo $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-gobject-structs.cc' object='libharfbuzz_gobject_la-hb-gobject-structs.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-buffer-serialize.lo `test -f 'hb-buffer-serialize.cc' || echo '$(srcdir)/'`hb-buffer-serialize.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_gobject_la-hb-gobject-structs.lo `test -f 'hb-gobject-structs.cc' || echo '$(srcdir)/'`hb-gobject-structs.cc
 
-libharfbuzz_fuzzing_la-hb-buffer.lo: hb-buffer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-buffer.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer.Tpo -c -o libharfbuzz_fuzzing_la-hb-buffer.lo `test -f 'hb-buffer.cc' || echo '$(srcdir)/'`hb-buffer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-buffer.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-buffer.cc' object='libharfbuzz_fuzzing_la-hb-buffer.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_gobject_la-hb-gobject-enums.lo: hb-gobject-enums.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_gobject_la-hb-gobject-enums.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Tpo -c -o libharfbuzz_gobject_la-hb-gobject-enums.lo `test -f 'hb-gobject-enums.cc' || echo '$(srcdir)/'`hb-gobject-enums.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Tpo $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-gobject-enums.cc' object='libharfbuzz_gobject_la-hb-gobject-enums.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-buffer.lo `test -f 'hb-buffer.cc' || echo '$(srcdir)/'`hb-buffer.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_gobject_la-hb-gobject-enums.lo `test -f 'hb-gobject-enums.cc' || echo '$(srcdir)/'`hb-gobject-enums.cc
 
-libharfbuzz_fuzzing_la-hb-common.lo: hb-common.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-common.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-common.Tpo -c -o libharfbuzz_fuzzing_la-hb-common.lo `test -f 'hb-common.cc' || echo '$(srcdir)/'`hb-common.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-common.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-common.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-common.cc' object='libharfbuzz_fuzzing_la-hb-common.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_icu_la-hb-icu.lo: hb-icu.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_icu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_icu_la-hb-icu.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Tpo -c -o libharfbuzz_icu_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Tpo $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-icu.cc' object='libharfbuzz_icu_la-hb-icu.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-common.lo `test -f 'hb-common.cc' || echo '$(srcdir)/'`hb-common.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_icu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_icu_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
 
-libharfbuzz_fuzzing_la-hb-face.lo: hb-face.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-face.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-face.Tpo -c -o libharfbuzz_fuzzing_la-hb-face.lo `test -f 'hb-face.cc' || echo '$(srcdir)/'`hb-face.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-face.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-face.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-face.cc' object='libharfbuzz_fuzzing_la-hb-face.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_subset_la-hb-ot-cff1-table.lo: hb-ot-cff1-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-ot-cff1-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff1-table.Tpo -c -o libharfbuzz_subset_la-hb-ot-cff1-table.lo `test -f 'hb-ot-cff1-table.cc' || echo '$(srcdir)/'`hb-ot-cff1-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff1-table.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff1-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-cff1-table.cc' object='libharfbuzz_subset_la-hb-ot-cff1-table.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-face.lo `test -f 'hb-face.cc' || echo '$(srcdir)/'`hb-face.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-ot-cff1-table.lo `test -f 'hb-ot-cff1-table.cc' || echo '$(srcdir)/'`hb-ot-cff1-table.cc
 
-libharfbuzz_fuzzing_la-hb-font.lo: hb-font.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-font.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-font.Tpo -c -o libharfbuzz_fuzzing_la-hb-font.lo `test -f 'hb-font.cc' || echo '$(srcdir)/'`hb-font.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-font.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-font.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-font.cc' object='libharfbuzz_fuzzing_la-hb-font.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_subset_la-hb-ot-cff2-table.lo: hb-ot-cff2-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-ot-cff2-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff2-table.Tpo -c -o libharfbuzz_subset_la-hb-ot-cff2-table.lo `test -f 'hb-ot-cff2-table.cc' || echo '$(srcdir)/'`hb-ot-cff2-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff2-table.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-ot-cff2-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-cff2-table.cc' object='libharfbuzz_subset_la-hb-ot-cff2-table.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-font.lo `test -f 'hb-font.cc' || echo '$(srcdir)/'`hb-font.cc
-
-libharfbuzz_fuzzing_la-hb-map.lo: hb-map.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-map.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-map.Tpo -c -o libharfbuzz_fuzzing_la-hb-map.lo `test -f 'hb-map.cc' || echo '$(srcdir)/'`hb-map.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-map.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-map.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-map.cc' object='libharfbuzz_fuzzing_la-hb-map.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-map.lo `test -f 'hb-map.cc' || echo '$(srcdir)/'`hb-map.cc
-
-libharfbuzz_fuzzing_la-hb-ot-tag.lo: hb-ot-tag.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-tag.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-tag.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-tag.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-tag.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-tag.cc' object='libharfbuzz_fuzzing_la-hb-ot-tag.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
-
-libharfbuzz_fuzzing_la-hb-set.lo: hb-set.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-set.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-set.Tpo -c -o libharfbuzz_fuzzing_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-set.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-set.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-set.cc' object='libharfbuzz_fuzzing_la-hb-set.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
-
-libharfbuzz_fuzzing_la-hb-shape.lo: hb-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape.Tpo -c -o libharfbuzz_fuzzing_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape.cc' object='libharfbuzz_fuzzing_la-hb-shape.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
-
-libharfbuzz_fuzzing_la-hb-shape-plan.lo: hb-shape-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-shape-plan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape-plan.Tpo -c -o libharfbuzz_fuzzing_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape-plan.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shape-plan.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape-plan.cc' object='libharfbuzz_fuzzing_la-hb-shape-plan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
-
-libharfbuzz_fuzzing_la-hb-shaper.lo: hb-shaper.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-shaper.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shaper.Tpo -c -o libharfbuzz_fuzzing_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shaper.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-shaper.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shaper.cc' object='libharfbuzz_fuzzing_la-hb-shaper.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
-
-libharfbuzz_fuzzing_la-hb-static.lo: hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-static.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-static.Tpo -c -o libharfbuzz_fuzzing_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-static.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-static.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='libharfbuzz_fuzzing_la-hb-static.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-
-libharfbuzz_fuzzing_la-hb-unicode.lo: hb-unicode.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-unicode.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-unicode.Tpo -c -o libharfbuzz_fuzzing_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-unicode.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-unicode.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-unicode.cc' object='libharfbuzz_fuzzing_la-hb-unicode.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
-
-libharfbuzz_fuzzing_la-hb-warning.lo: hb-warning.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-warning.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-warning.Tpo -c -o libharfbuzz_fuzzing_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-warning.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-warning.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-warning.cc' object='libharfbuzz_fuzzing_la-hb-warning.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
-
-libharfbuzz_fuzzing_la-hb-aat-layout.lo: hb-aat-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-aat-layout.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-aat-layout.Tpo -c -o libharfbuzz_fuzzing_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-aat-layout.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-aat-layout.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-aat-layout.cc' object='libharfbuzz_fuzzing_la-hb-aat-layout.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
-
-libharfbuzz_fuzzing_la-hb-ot-font.lo: hb-ot-font.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-font.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-font.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-font.lo `test -f 'hb-ot-font.cc' || echo '$(srcdir)/'`hb-ot-font.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-font.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-font.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-font.cc' object='libharfbuzz_fuzzing_la-hb-ot-font.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-font.lo `test -f 'hb-ot-font.cc' || echo '$(srcdir)/'`hb-ot-font.cc
-
-libharfbuzz_fuzzing_la-hb-ot-layout.lo: hb-ot-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-layout.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-layout.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-layout.lo `test -f 'hb-ot-layout.cc' || echo '$(srcdir)/'`hb-ot-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-layout.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-layout.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-layout.cc' object='libharfbuzz_fuzzing_la-hb-ot-layout.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-layout.lo `test -f 'hb-ot-layout.cc' || echo '$(srcdir)/'`hb-ot-layout.cc
-
-libharfbuzz_fuzzing_la-hb-ot-color.lo: hb-ot-color.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-color.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-color.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-color.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-color.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-color.cc' object='libharfbuzz_fuzzing_la-hb-ot-color.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
-
-libharfbuzz_fuzzing_la-hb-ot-map.lo: hb-ot-map.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-map.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-map.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-map.lo `test -f 'hb-ot-map.cc' || echo '$(srcdir)/'`hb-ot-map.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-map.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-map.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-map.cc' object='libharfbuzz_fuzzing_la-hb-ot-map.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-map.lo `test -f 'hb-ot-map.cc' || echo '$(srcdir)/'`hb-ot-map.cc
-
-libharfbuzz_fuzzing_la-hb-ot-math.lo: hb-ot-math.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-math.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-math.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-math.lo `test -f 'hb-ot-math.cc' || echo '$(srcdir)/'`hb-ot-math.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-math.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-math.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-math.cc' object='libharfbuzz_fuzzing_la-hb-ot-math.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-math.lo `test -f 'hb-ot-math.cc' || echo '$(srcdir)/'`hb-ot-math.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape.lo: hb-ot-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo: hb-ot-shape-complex-arabic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo `test -f 'hb-ot-shape-complex-arabic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-arabic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-arabic.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-arabic.lo `test -f 'hb-ot-shape-complex-arabic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-arabic.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo: hb-ot-shape-complex-default.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo `test -f 'hb-ot-shape-complex-default.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-default.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-default.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-default.lo `test -f 'hb-ot-shape-complex-default.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-default.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo: hb-ot-shape-complex-hangul.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo `test -f 'hb-ot-shape-complex-hangul.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-hangul.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-hangul.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-hangul.lo `test -f 'hb-ot-shape-complex-hangul.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-hangul.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo: hb-ot-shape-complex-hebrew.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo `test -f 'hb-ot-shape-complex-hebrew.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-hebrew.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-hebrew.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-hebrew.lo `test -f 'hb-ot-shape-complex-hebrew.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-hebrew.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo: hb-ot-shape-complex-indic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-indic.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo: hb-ot-shape-complex-indic-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo `test -f 'hb-ot-shape-complex-indic-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-indic-table.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-indic-table.lo `test -f 'hb-ot-shape-complex-indic-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic-table.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo: hb-ot-shape-complex-khmer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo `test -f 'hb-ot-shape-complex-khmer.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-khmer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-khmer.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-khmer.lo `test -f 'hb-ot-shape-complex-khmer.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-khmer.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo: hb-ot-shape-complex-myanmar.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo `test -f 'hb-ot-shape-complex-myanmar.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-myanmar.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-myanmar.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-myanmar.lo `test -f 'hb-ot-shape-complex-myanmar.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-myanmar.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo: hb-ot-shape-complex-thai.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo `test -f 'hb-ot-shape-complex-thai.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-thai.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-thai.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-thai.lo `test -f 'hb-ot-shape-complex-thai.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-thai.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo: hb-ot-shape-complex-tibetan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo `test -f 'hb-ot-shape-complex-tibetan.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-tibetan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-tibetan.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-tibetan.lo `test -f 'hb-ot-shape-complex-tibetan.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-tibetan.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo: hb-ot-shape-complex-use.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo `test -f 'hb-ot-shape-complex-use.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-use.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-use.lo `test -f 'hb-ot-shape-complex-use.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo: hb-ot-shape-complex-use-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-use-table.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo: hb-ot-shape-normalize.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-normalize.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo `test -f 'hb-ot-shape-normalize.cc' || echo '$(srcdir)/'`hb-ot-shape-normalize.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-normalize.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-normalize.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-normalize.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-normalize.lo `test -f 'hb-ot-shape-normalize.cc' || echo '$(srcdir)/'`hb-ot-shape-normalize.cc
-
-libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo: hb-ot-shape-fallback.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-fallback.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-fallback.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-shape-fallback.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-fallback.cc' object='libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
-
-libharfbuzz_fuzzing_la-hb-ot-var.lo: hb-ot-var.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ot-var.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-var.Tpo -c -o libharfbuzz_fuzzing_la-hb-ot-var.lo `test -f 'hb-ot-var.cc' || echo '$(srcdir)/'`hb-ot-var.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-var.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ot-var.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-var.cc' object='libharfbuzz_fuzzing_la-hb-ot-var.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ot-var.lo `test -f 'hb-ot-var.cc' || echo '$(srcdir)/'`hb-ot-var.cc
-
-libharfbuzz_fuzzing_la-hb-fallback-shape.lo: hb-fallback-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-fallback-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-fallback-shape.Tpo -c -o libharfbuzz_fuzzing_la-hb-fallback-shape.lo `test -f 'hb-fallback-shape.cc' || echo '$(srcdir)/'`hb-fallback-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-fallback-shape.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-fallback-shape.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-fallback-shape.cc' object='libharfbuzz_fuzzing_la-hb-fallback-shape.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-fallback-shape.lo `test -f 'hb-fallback-shape.cc' || echo '$(srcdir)/'`hb-fallback-shape.cc
-
-libharfbuzz_fuzzing_la-hb-glib.lo: hb-glib.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-glib.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-glib.Tpo -c -o libharfbuzz_fuzzing_la-hb-glib.lo `test -f 'hb-glib.cc' || echo '$(srcdir)/'`hb-glib.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-glib.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-glib.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-glib.cc' object='libharfbuzz_fuzzing_la-hb-glib.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-glib.lo `test -f 'hb-glib.cc' || echo '$(srcdir)/'`hb-glib.cc
-
-libharfbuzz_fuzzing_la-hb-ft.lo: hb-ft.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ft.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ft.Tpo -c -o libharfbuzz_fuzzing_la-hb-ft.lo `test -f 'hb-ft.cc' || echo '$(srcdir)/'`hb-ft.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ft.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ft.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ft.cc' object='libharfbuzz_fuzzing_la-hb-ft.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ft.lo `test -f 'hb-ft.cc' || echo '$(srcdir)/'`hb-ft.cc
-
-libharfbuzz_fuzzing_la-hb-graphite2.lo: hb-graphite2.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-graphite2.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-graphite2.Tpo -c -o libharfbuzz_fuzzing_la-hb-graphite2.lo `test -f 'hb-graphite2.cc' || echo '$(srcdir)/'`hb-graphite2.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-graphite2.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-graphite2.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-graphite2.cc' object='libharfbuzz_fuzzing_la-hb-graphite2.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-graphite2.lo `test -f 'hb-graphite2.cc' || echo '$(srcdir)/'`hb-graphite2.cc
-
-libharfbuzz_fuzzing_la-hb-uniscribe.lo: hb-uniscribe.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-uniscribe.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-uniscribe.Tpo -c -o libharfbuzz_fuzzing_la-hb-uniscribe.lo `test -f 'hb-uniscribe.cc' || echo '$(srcdir)/'`hb-uniscribe.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-uniscribe.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-uniscribe.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-uniscribe.cc' object='libharfbuzz_fuzzing_la-hb-uniscribe.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-uniscribe.lo `test -f 'hb-uniscribe.cc' || echo '$(srcdir)/'`hb-uniscribe.cc
-
-libharfbuzz_fuzzing_la-hb-directwrite.lo: hb-directwrite.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-directwrite.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-directwrite.Tpo -c -o libharfbuzz_fuzzing_la-hb-directwrite.lo `test -f 'hb-directwrite.cc' || echo '$(srcdir)/'`hb-directwrite.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-directwrite.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-directwrite.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-directwrite.cc' object='libharfbuzz_fuzzing_la-hb-directwrite.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-directwrite.lo `test -f 'hb-directwrite.cc' || echo '$(srcdir)/'`hb-directwrite.cc
-
-libharfbuzz_fuzzing_la-hb-coretext.lo: hb-coretext.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-coretext.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-coretext.Tpo -c -o libharfbuzz_fuzzing_la-hb-coretext.lo `test -f 'hb-coretext.cc' || echo '$(srcdir)/'`hb-coretext.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-coretext.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-coretext.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-coretext.cc' object='libharfbuzz_fuzzing_la-hb-coretext.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-coretext.lo `test -f 'hb-coretext.cc' || echo '$(srcdir)/'`hb-coretext.cc
-
-libharfbuzz_fuzzing_la-hb-ucdn.lo: hb-ucdn.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-ucdn.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ucdn.Tpo -c -o libharfbuzz_fuzzing_la-hb-ucdn.lo `test -f 'hb-ucdn.cc' || echo '$(srcdir)/'`hb-ucdn.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ucdn.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-ucdn.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ucdn.cc' object='libharfbuzz_fuzzing_la-hb-ucdn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-ucdn.lo `test -f 'hb-ucdn.cc' || echo '$(srcdir)/'`hb-ucdn.cc
-
-libharfbuzz_fuzzing_la-hb-icu.lo: hb-icu.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_fuzzing_la-hb-icu.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_fuzzing_la-hb-icu.Tpo -c -o libharfbuzz_fuzzing_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_fuzzing_la-hb-icu.Tpo $(DEPDIR)/libharfbuzz_fuzzing_la-hb-icu.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-icu.cc' object='libharfbuzz_fuzzing_la-hb-icu.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_fuzzing_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
-
-libharfbuzz_gobject_la-hb-gobject-structs.lo: hb-gobject-structs.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_gobject_la-hb-gobject-structs.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Tpo -c -o libharfbuzz_gobject_la-hb-gobject-structs.lo `test -f 'hb-gobject-structs.cc' || echo '$(srcdir)/'`hb-gobject-structs.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Tpo $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-structs.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-gobject-structs.cc' object='libharfbuzz_gobject_la-hb-gobject-structs.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_gobject_la-hb-gobject-structs.lo `test -f 'hb-gobject-structs.cc' || echo '$(srcdir)/'`hb-gobject-structs.cc
-
-libharfbuzz_gobject_la-hb-gobject-enums.lo: hb-gobject-enums.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_gobject_la-hb-gobject-enums.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Tpo -c -o libharfbuzz_gobject_la-hb-gobject-enums.lo `test -f 'hb-gobject-enums.cc' || echo '$(srcdir)/'`hb-gobject-enums.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Tpo $(DEPDIR)/libharfbuzz_gobject_la-hb-gobject-enums.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-gobject-enums.cc' object='libharfbuzz_gobject_la-hb-gobject-enums.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_gobject_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_gobject_la-hb-gobject-enums.lo `test -f 'hb-gobject-enums.cc' || echo '$(srcdir)/'`hb-gobject-enums.cc
-
-libharfbuzz_icu_la-hb-icu.lo: hb-icu.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_icu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_icu_la-hb-icu.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Tpo -c -o libharfbuzz_icu_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Tpo $(DEPDIR)/libharfbuzz_icu_la-hb-icu.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-icu.cc' object='libharfbuzz_icu_la-hb-icu.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_icu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_icu_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
-
-libharfbuzz_subset_fuzzing_la-hb-static.lo: hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_fuzzing_la-hb-static.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-static.Tpo -c -o libharfbuzz_subset_fuzzing_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-static.Tpo $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-static.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='libharfbuzz_subset_fuzzing_la-hb-static.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_fuzzing_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-
-libharfbuzz_subset_fuzzing_la-hb-subset.lo: hb-subset.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_fuzzing_la-hb-subset.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset.Tpo -c -o libharfbuzz_subset_fuzzing_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset.Tpo $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset.cc' object='libharfbuzz_subset_fuzzing_la-hb-subset.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_fuzzing_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
-
-libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo: hb-subset-glyf.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-glyf.Tpo -c -o libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo `test -f 'hb-subset-glyf.cc' || echo '$(srcdir)/'`hb-subset-glyf.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-glyf.Tpo $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-glyf.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-glyf.cc' object='libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_fuzzing_la-hb-subset-glyf.lo `test -f 'hb-subset-glyf.cc' || echo '$(srcdir)/'`hb-subset-glyf.cc
-
-libharfbuzz_subset_fuzzing_la-hb-subset-input.lo: hb-subset-input.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_fuzzing_la-hb-subset-input.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-input.Tpo -c -o libharfbuzz_subset_fuzzing_la-hb-subset-input.lo `test -f 'hb-subset-input.cc' || echo '$(srcdir)/'`hb-subset-input.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-input.Tpo $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-input.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-input.cc' object='libharfbuzz_subset_fuzzing_la-hb-subset-input.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_fuzzing_la-hb-subset-input.lo `test -f 'hb-subset-input.cc' || echo '$(srcdir)/'`hb-subset-input.cc
-
-libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo: hb-subset-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-plan.Tpo -c -o libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo `test -f 'hb-subset-plan.cc' || echo '$(srcdir)/'`hb-subset-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-plan.Tpo $(DEPDIR)/libharfbuzz_subset_fuzzing_la-hb-subset-plan.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-plan.cc' object='libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_fuzzing_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_fuzzing_la-hb-subset-plan.lo `test -f 'hb-subset-plan.cc' || echo '$(srcdir)/'`hb-subset-plan.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-ot-cff2-table.lo `test -f 'hb-ot-cff2-table.cc' || echo '$(srcdir)/'`hb-ot-cff2-table.cc
 
 libharfbuzz_subset_la-hb-static.lo: hb-static.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-static.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-static.Tpo -c -o libharfbuzz_subset_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
@@ -2335,12 +1837,26 @@ libharfbuzz_subset_la-hb-static.lo: hb-static.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
 
-libharfbuzz_subset_la-hb-subset.lo: hb-subset.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Tpo -c -o libharfbuzz_subset_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset.cc' object='libharfbuzz_subset_la-hb-subset.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_subset_la-hb-subset-cff-common.lo: hb-subset-cff-common.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset-cff-common.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff-common.Tpo -c -o libharfbuzz_subset_la-hb-subset-cff-common.lo `test -f 'hb-subset-cff-common.cc' || echo '$(srcdir)/'`hb-subset-cff-common.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff-common.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff-common.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-cff-common.cc' object='libharfbuzz_subset_la-hb-subset-cff-common.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset-cff-common.lo `test -f 'hb-subset-cff-common.cc' || echo '$(srcdir)/'`hb-subset-cff-common.cc
+
+libharfbuzz_subset_la-hb-subset-cff1.lo: hb-subset-cff1.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset-cff1.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff1.Tpo -c -o libharfbuzz_subset_la-hb-subset-cff1.lo `test -f 'hb-subset-cff1.cc' || echo '$(srcdir)/'`hb-subset-cff1.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff1.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff1.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-cff1.cc' object='libharfbuzz_subset_la-hb-subset-cff1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset-cff1.lo `test -f 'hb-subset-cff1.cc' || echo '$(srcdir)/'`hb-subset-cff1.cc
+
+libharfbuzz_subset_la-hb-subset-cff2.lo: hb-subset-cff2.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset-cff2.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff2.Tpo -c -o libharfbuzz_subset_la-hb-subset-cff2.lo `test -f 'hb-subset-cff2.cc' || echo '$(srcdir)/'`hb-subset-cff2.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff2.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-subset-cff2.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-cff2.cc' object='libharfbuzz_subset_la-hb-subset-cff2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset-cff2.lo `test -f 'hb-subset-cff2.cc' || echo '$(srcdir)/'`hb-subset-cff2.cc
 
 libharfbuzz_subset_la-hb-subset-glyf.lo: hb-subset-glyf.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset-glyf.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset-glyf.Tpo -c -o libharfbuzz_subset_la-hb-subset-glyf.lo `test -f 'hb-subset-glyf.cc' || echo '$(srcdir)/'`hb-subset-glyf.cc
@@ -2363,6 +1879,27 @@ libharfbuzz_subset_la-hb-subset-plan.lo: hb-subset-plan.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset-plan.lo `test -f 'hb-subset-plan.cc' || echo '$(srcdir)/'`hb-subset-plan.cc
 
+libharfbuzz_subset_la-hb-subset.lo: hb-subset.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_subset_la-hb-subset.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Tpo -c -o libharfbuzz_subset_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Tpo $(DEPDIR)/libharfbuzz_subset_la-hb-subset.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset.cc' object='libharfbuzz_subset_la-hb-subset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_subset_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_subset_la-hb-subset.lo `test -f 'hb-subset.cc' || echo '$(srcdir)/'`hb-subset.cc
+
+libharfbuzz_la-hb-aat-layout.lo: hb-aat-layout.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-aat-layout.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Tpo -c -o libharfbuzz_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Tpo $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-aat-layout.cc' object='libharfbuzz_la-hb-aat-layout.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
+
+libharfbuzz_la-hb-aat-map.lo: hb-aat-map.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-aat-map.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-aat-map.Tpo -c -o libharfbuzz_la-hb-aat-map.lo `test -f 'hb-aat-map.cc' || echo '$(srcdir)/'`hb-aat-map.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-aat-map.Tpo $(DEPDIR)/libharfbuzz_la-hb-aat-map.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-aat-map.cc' object='libharfbuzz_la-hb-aat-map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-aat-map.lo `test -f 'hb-aat-map.cc' || echo '$(srcdir)/'`hb-aat-map.cc
+
 libharfbuzz_la-hb-blob.lo: hb-blob.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-blob.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-blob.Tpo -c -o libharfbuzz_la-hb-blob.lo `test -f 'hb-blob.cc' || echo '$(srcdir)/'`hb-blob.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-blob.Tpo $(DEPDIR)/libharfbuzz_la-hb-blob.Plo
@@ -2412,68 +1949,33 @@ libharfbuzz_la-hb-map.lo: hb-map.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-map.lo `test -f 'hb-map.cc' || echo '$(srcdir)/'`hb-map.cc
 
-libharfbuzz_la-hb-ot-tag.lo: hb-ot-tag.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-tag.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Tpo -c -o libharfbuzz_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-tag.cc' object='libharfbuzz_la-hb-ot-tag.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
-
-libharfbuzz_la-hb-set.lo: hb-set.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-set.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-set.Tpo -c -o libharfbuzz_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-set.Tpo $(DEPDIR)/libharfbuzz_la-hb-set.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-set.cc' object='libharfbuzz_la-hb-set.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
-
-libharfbuzz_la-hb-shape.lo: hb-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shape.Tpo -c -o libharfbuzz_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shape.Tpo $(DEPDIR)/libharfbuzz_la-hb-shape.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape.cc' object='libharfbuzz_la-hb-shape.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
-
-libharfbuzz_la-hb-shape-plan.lo: hb-shape-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shape-plan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Tpo -c -o libharfbuzz_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Tpo $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape-plan.cc' object='libharfbuzz_la-hb-shape-plan.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-cff1-table.lo: hb-ot-cff1-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-cff1-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-cff1-table.Tpo -c -o libharfbuzz_la-hb-ot-cff1-table.lo `test -f 'hb-ot-cff1-table.cc' || echo '$(srcdir)/'`hb-ot-cff1-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-cff1-table.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-cff1-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-cff1-table.cc' object='libharfbuzz_la-hb-ot-cff1-table.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-cff1-table.lo `test -f 'hb-ot-cff1-table.cc' || echo '$(srcdir)/'`hb-ot-cff1-table.cc
 
-libharfbuzz_la-hb-shaper.lo: hb-shaper.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shaper.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shaper.Tpo -c -o libharfbuzz_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shaper.Tpo $(DEPDIR)/libharfbuzz_la-hb-shaper.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shaper.cc' object='libharfbuzz_la-hb-shaper.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-cff2-table.lo: hb-ot-cff2-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-cff2-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-cff2-table.Tpo -c -o libharfbuzz_la-hb-ot-cff2-table.lo `test -f 'hb-ot-cff2-table.cc' || echo '$(srcdir)/'`hb-ot-cff2-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-cff2-table.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-cff2-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-cff2-table.cc' object='libharfbuzz_la-hb-ot-cff2-table.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-cff2-table.lo `test -f 'hb-ot-cff2-table.cc' || echo '$(srcdir)/'`hb-ot-cff2-table.cc
 
-libharfbuzz_la-hb-static.lo: hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-static.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-static.Tpo -c -o libharfbuzz_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-static.Tpo $(DEPDIR)/libharfbuzz_la-hb-static.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='libharfbuzz_la-hb-static.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
-
-libharfbuzz_la-hb-unicode.lo: hb-unicode.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-unicode.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-unicode.Tpo -c -o libharfbuzz_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-unicode.Tpo $(DEPDIR)/libharfbuzz_la-hb-unicode.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-unicode.cc' object='libharfbuzz_la-hb-unicode.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-color.lo: hb-ot-color.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-color.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-color.Tpo -c -o libharfbuzz_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-color.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-color.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-color.cc' object='libharfbuzz_la-hb-ot-color.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
 
-libharfbuzz_la-hb-warning.lo: hb-warning.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-warning.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-warning.Tpo -c -o libharfbuzz_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-warning.Tpo $(DEPDIR)/libharfbuzz_la-hb-warning.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-warning.cc' object='libharfbuzz_la-hb-warning.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-face.lo: hb-ot-face.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-face.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-face.Tpo -c -o libharfbuzz_la-hb-ot-face.lo `test -f 'hb-ot-face.cc' || echo '$(srcdir)/'`hb-ot-face.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-face.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-face.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-face.cc' object='libharfbuzz_la-hb-ot-face.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
-
-libharfbuzz_la-hb-aat-layout.lo: hb-aat-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-aat-layout.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Tpo -c -o libharfbuzz_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Tpo $(DEPDIR)/libharfbuzz_la-hb-aat-layout.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-aat-layout.cc' object='libharfbuzz_la-hb-aat-layout.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-aat-layout.lo `test -f 'hb-aat-layout.cc' || echo '$(srcdir)/'`hb-aat-layout.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-face.lo `test -f 'hb-ot-face.cc' || echo '$(srcdir)/'`hb-ot-face.cc
 
 libharfbuzz_la-hb-ot-font.lo: hb-ot-font.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-font.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-font.Tpo -c -o libharfbuzz_la-hb-ot-font.lo `test -f 'hb-ot-font.cc' || echo '$(srcdir)/'`hb-ot-font.cc
@@ -2489,13 +1991,6 @@ libharfbuzz_la-hb-ot-layout.lo: hb-ot-layout.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-layout.lo `test -f 'hb-ot-layout.cc' || echo '$(srcdir)/'`hb-ot-layout.cc
 
-libharfbuzz_la-hb-ot-color.lo: hb-ot-color.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-color.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-color.Tpo -c -o libharfbuzz_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-color.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-color.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-color.cc' object='libharfbuzz_la-hb-ot-color.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-color.lo `test -f 'hb-ot-color.cc' || echo '$(srcdir)/'`hb-ot-color.cc
-
 libharfbuzz_la-hb-ot-map.lo: hb-ot-map.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-map.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-map.Tpo -c -o libharfbuzz_la-hb-ot-map.lo `test -f 'hb-ot-map.cc' || echo '$(srcdir)/'`hb-ot-map.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-map.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-map.Plo
@@ -2510,12 +2005,19 @@ libharfbuzz_la-hb-ot-math.lo: hb-ot-math.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-math.lo `test -f 'hb-ot-math.cc' || echo '$(srcdir)/'`hb-ot-math.cc
 
-libharfbuzz_la-hb-ot-shape.lo: hb-ot-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Tpo -c -o libharfbuzz_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape.cc' object='libharfbuzz_la-hb-ot-shape.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-name-language.lo: hb-ot-name-language.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-name-language.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-name-language.Tpo -c -o libharfbuzz_la-hb-ot-name-language.lo `test -f 'hb-ot-name-language.cc' || echo '$(srcdir)/'`hb-ot-name-language.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-name-language.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-name-language.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-name-language.cc' object='libharfbuzz_la-hb-ot-name-language.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-name-language.lo `test -f 'hb-ot-name-language.cc' || echo '$(srcdir)/'`hb-ot-name-language.cc
+
+libharfbuzz_la-hb-ot-name.lo: hb-ot-name.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-name.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-name.Tpo -c -o libharfbuzz_la-hb-ot-name.lo `test -f 'hb-ot-name.cc' || echo '$(srcdir)/'`hb-ot-name.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-name.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-name.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-name.cc' object='libharfbuzz_la-hb-ot-name.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-name.lo `test -f 'hb-ot-name.cc' || echo '$(srcdir)/'`hb-ot-name.cc
 
 libharfbuzz_la-hb-ot-shape-complex-arabic.lo: hb-ot-shape-complex-arabic.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-arabic.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-arabic.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-arabic.lo `test -f 'hb-ot-shape-complex-arabic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-arabic.cc
@@ -2545,13 +2047,6 @@ libharfbuzz_la-hb-ot-shape-complex-hebrew.lo: hb-ot-shape-complex-hebrew.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-hebrew.lo `test -f 'hb-ot-shape-complex-hebrew.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-hebrew.cc
 
-libharfbuzz_la-hb-ot-shape-complex-indic.lo: hb-ot-shape-complex-indic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-indic.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-indic.cc' object='libharfbuzz_la-hb-ot-shape-complex-indic.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
-
 libharfbuzz_la-hb-ot-shape-complex-indic-table.lo: hb-ot-shape-complex-indic-table.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-indic-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic-table.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-indic-table.lo `test -f 'hb-ot-shape-complex-indic-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic-table.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic-table.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic-table.Plo
@@ -2559,6 +2054,13 @@ libharfbuzz_la-hb-ot-shape-complex-indic-table.lo: hb-ot-shape-complex-indic-tab
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-indic-table.lo `test -f 'hb-ot-shape-complex-indic-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic-table.cc
 
+libharfbuzz_la-hb-ot-shape-complex-indic.lo: hb-ot-shape-complex-indic.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-indic.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-indic.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-indic.cc' object='libharfbuzz_la-hb-ot-shape-complex-indic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-indic.lo `test -f 'hb-ot-shape-complex-indic.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-indic.cc
+
 libharfbuzz_la-hb-ot-shape-complex-khmer.lo: hb-ot-shape-complex-khmer.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-khmer.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-khmer.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-khmer.lo `test -f 'hb-ot-shape-complex-khmer.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-khmer.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-khmer.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-khmer.Plo
@@ -2580,12 +2082,12 @@ libharfbuzz_la-hb-ot-shape-complex-thai.lo: hb-ot-shape-complex-thai.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-thai.lo `test -f 'hb-ot-shape-complex-thai.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-thai.cc
 
-libharfbuzz_la-hb-ot-shape-complex-tibetan.lo: hb-ot-shape-complex-tibetan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-tibetan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-tibetan.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-tibetan.lo `test -f 'hb-ot-shape-complex-tibetan.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-tibetan.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-tibetan.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-tibetan.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-tibetan.cc' object='libharfbuzz_la-hb-ot-shape-complex-tibetan.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-shape-complex-use-table.lo: hb-ot-shape-complex-use-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-use-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-use-table.cc' object='libharfbuzz_la-hb-ot-shape-complex-use-table.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-tibetan.lo `test -f 'hb-ot-shape-complex-tibetan.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-tibetan.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
 
 libharfbuzz_la-hb-ot-shape-complex-use.lo: hb-ot-shape-complex-use.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-use.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-use.lo `test -f 'hb-ot-shape-complex-use.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use.cc
@@ -2594,12 +2096,19 @@ libharfbuzz_la-hb-ot-shape-complex-use.lo: hb-ot-shape-complex-use.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-use.lo `test -f 'hb-ot-shape-complex-use.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use.cc
 
-libharfbuzz_la-hb-ot-shape-complex-use-table.lo: hb-ot-shape-complex-use-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-use-table.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-use-table.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-use-table.cc' object='libharfbuzz_la-hb-ot-shape-complex-use-table.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo: hb-ot-shape-complex-vowel-constraints.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.Tpo -c -o libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo `test -f 'hb-ot-shape-complex-vowel-constraints.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-vowel-constraints.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-complex-vowel-constraints.cc' object='libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-use-table.lo `test -f 'hb-ot-shape-complex-use-table.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-use-table.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-complex-vowel-constraints.lo `test -f 'hb-ot-shape-complex-vowel-constraints.cc' || echo '$(srcdir)/'`hb-ot-shape-complex-vowel-constraints.cc
+
+libharfbuzz_la-hb-ot-shape-fallback.lo: hb-ot-shape-fallback.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-fallback.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Tpo -c -o libharfbuzz_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-fallback.cc' object='libharfbuzz_la-hb-ot-shape-fallback.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
 
 libharfbuzz_la-hb-ot-shape-normalize.lo: hb-ot-shape-normalize.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-normalize.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-normalize.Tpo -c -o libharfbuzz_la-hb-ot-shape-normalize.lo `test -f 'hb-ot-shape-normalize.cc' || echo '$(srcdir)/'`hb-ot-shape-normalize.cc
@@ -2608,12 +2117,19 @@ libharfbuzz_la-hb-ot-shape-normalize.lo: hb-ot-shape-normalize.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-normalize.lo `test -f 'hb-ot-shape-normalize.cc' || echo '$(srcdir)/'`hb-ot-shape-normalize.cc
 
-libharfbuzz_la-hb-ot-shape-fallback.lo: hb-ot-shape-fallback.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape-fallback.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Tpo -c -o libharfbuzz_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape-fallback.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape-fallback.cc' object='libharfbuzz_la-hb-ot-shape-fallback.lo' libtool=yes @AMDEPBACKSLASH@
+libharfbuzz_la-hb-ot-shape.lo: hb-ot-shape.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Tpo -c -o libharfbuzz_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-shape.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-shape.cc' object='libharfbuzz_la-hb-ot-shape.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape-fallback.lo `test -f 'hb-ot-shape-fallback.cc' || echo '$(srcdir)/'`hb-ot-shape-fallback.cc
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-shape.lo `test -f 'hb-ot-shape.cc' || echo '$(srcdir)/'`hb-ot-shape.cc
+
+libharfbuzz_la-hb-ot-tag.lo: hb-ot-tag.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-tag.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Tpo -c -o libharfbuzz_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Tpo $(DEPDIR)/libharfbuzz_la-hb-ot-tag.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-ot-tag.cc' object='libharfbuzz_la-hb-ot-tag.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-tag.lo `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
 
 libharfbuzz_la-hb-ot-var.lo: hb-ot-var.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-ot-var.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-ot-var.Tpo -c -o libharfbuzz_la-hb-ot-var.lo `test -f 'hb-ot-var.cc' || echo '$(srcdir)/'`hb-ot-var.cc
@@ -2622,6 +2138,55 @@ libharfbuzz_la-hb-ot-var.lo: hb-ot-var.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-ot-var.lo `test -f 'hb-ot-var.cc' || echo '$(srcdir)/'`hb-ot-var.cc
 
+libharfbuzz_la-hb-set.lo: hb-set.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-set.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-set.Tpo -c -o libharfbuzz_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-set.Tpo $(DEPDIR)/libharfbuzz_la-hb-set.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-set.cc' object='libharfbuzz_la-hb-set.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-set.lo `test -f 'hb-set.cc' || echo '$(srcdir)/'`hb-set.cc
+
+libharfbuzz_la-hb-shape-plan.lo: hb-shape-plan.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shape-plan.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Tpo -c -o libharfbuzz_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Tpo $(DEPDIR)/libharfbuzz_la-hb-shape-plan.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape-plan.cc' object='libharfbuzz_la-hb-shape-plan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shape-plan.lo `test -f 'hb-shape-plan.cc' || echo '$(srcdir)/'`hb-shape-plan.cc
+
+libharfbuzz_la-hb-shape.lo: hb-shape.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shape.Tpo -c -o libharfbuzz_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shape.Tpo $(DEPDIR)/libharfbuzz_la-hb-shape.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shape.cc' object='libharfbuzz_la-hb-shape.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shape.lo `test -f 'hb-shape.cc' || echo '$(srcdir)/'`hb-shape.cc
+
+libharfbuzz_la-hb-shaper.lo: hb-shaper.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-shaper.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-shaper.Tpo -c -o libharfbuzz_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-shaper.Tpo $(DEPDIR)/libharfbuzz_la-hb-shaper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-shaper.cc' object='libharfbuzz_la-hb-shaper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-shaper.lo `test -f 'hb-shaper.cc' || echo '$(srcdir)/'`hb-shaper.cc
+
+libharfbuzz_la-hb-static.lo: hb-static.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-static.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-static.Tpo -c -o libharfbuzz_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-static.Tpo $(DEPDIR)/libharfbuzz_la-hb-static.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='libharfbuzz_la-hb-static.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-static.lo `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
+
+libharfbuzz_la-hb-unicode.lo: hb-unicode.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-unicode.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-unicode.Tpo -c -o libharfbuzz_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-unicode.Tpo $(DEPDIR)/libharfbuzz_la-hb-unicode.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-unicode.cc' object='libharfbuzz_la-hb-unicode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-unicode.lo `test -f 'hb-unicode.cc' || echo '$(srcdir)/'`hb-unicode.cc
+
+libharfbuzz_la-hb-warning.lo: hb-warning.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-warning.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-warning.Tpo -c -o libharfbuzz_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-warning.Tpo $(DEPDIR)/libharfbuzz_la-hb-warning.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-warning.cc' object='libharfbuzz_la-hb-warning.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-warning.lo `test -f 'hb-warning.cc' || echo '$(srcdir)/'`hb-warning.cc
+
 libharfbuzz_la-hb-fallback-shape.lo: hb-fallback-shape.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libharfbuzz_la-hb-fallback-shape.lo -MD -MP -MF $(DEPDIR)/libharfbuzz_la-hb-fallback-shape.Tpo -c -o libharfbuzz_la-hb-fallback-shape.lo `test -f 'hb-fallback-shape.cc' || echo '$(srcdir)/'`hb-fallback-shape.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libharfbuzz_la-hb-fallback-shape.Tpo $(DEPDIR)/libharfbuzz_la-hb-fallback-shape.Plo
@@ -2685,34 +2250,6 @@ libharfbuzz_la-hb-icu.lo: hb-icu.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libharfbuzz_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libharfbuzz_la-hb-icu.lo `test -f 'hb-icu.cc' || echo '$(srcdir)/'`hb-icu.cc
 
-dump_emoji-dump-emoji.o: dump-emoji.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_emoji_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dump_emoji-dump-emoji.o -MD -MP -MF $(DEPDIR)/dump_emoji-dump-emoji.Tpo -c -o dump_emoji-dump-emoji.o `test -f 'dump-emoji.cc' || echo '$(srcdir)/'`dump-emoji.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/dump_emoji-dump-emoji.Tpo $(DEPDIR)/dump_emoji-dump-emoji.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='dump-emoji.cc' object='dump_emoji-dump-emoji.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_emoji_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dump_emoji-dump-emoji.o `test -f 'dump-emoji.cc' || echo '$(srcdir)/'`dump-emoji.cc
-
-dump_emoji-dump-emoji.obj: dump-emoji.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_emoji_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dump_emoji-dump-emoji.obj -MD -MP -MF $(DEPDIR)/dump_emoji-dump-emoji.Tpo -c -o dump_emoji-dump-emoji.obj `if test -f 'dump-emoji.cc'; then $(CYGPATH_W) 'dump-emoji.cc'; else $(CYGPATH_W) '$(srcdir)/dump-emoji.cc'; fi`
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/dump_emoji-dump-emoji.Tpo $(DEPDIR)/dump_emoji-dump-emoji.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='dump-emoji.cc' object='dump_emoji-dump-emoji.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_emoji_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dump_emoji-dump-emoji.obj `if test -f 'dump-emoji.cc'; then $(CYGPATH_W) 'dump-emoji.cc'; else $(CYGPATH_W) '$(srcdir)/dump-emoji.cc'; fi`
-
-dump_fon-dump-fon.o: dump-fon.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_fon_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dump_fon-dump-fon.o -MD -MP -MF $(DEPDIR)/dump_fon-dump-fon.Tpo -c -o dump_fon-dump-fon.o `test -f 'dump-fon.cc' || echo '$(srcdir)/'`dump-fon.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/dump_fon-dump-fon.Tpo $(DEPDIR)/dump_fon-dump-fon.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='dump-fon.cc' object='dump_fon-dump-fon.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_fon_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dump_fon-dump-fon.o `test -f 'dump-fon.cc' || echo '$(srcdir)/'`dump-fon.cc
-
-dump_fon-dump-fon.obj: dump-fon.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_fon_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dump_fon-dump-fon.obj -MD -MP -MF $(DEPDIR)/dump_fon-dump-fon.Tpo -c -o dump_fon-dump-fon.obj `if test -f 'dump-fon.cc'; then $(CYGPATH_W) 'dump-fon.cc'; else $(CYGPATH_W) '$(srcdir)/dump-fon.cc'; fi`
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/dump_fon-dump-fon.Tpo $(DEPDIR)/dump_fon-dump-fon.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='dump-fon.cc' object='dump_fon-dump-fon.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_fon_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dump_fon-dump-fon.obj `if test -f 'dump-fon.cc'; then $(CYGPATH_W) 'dump-fon.cc'; else $(CYGPATH_W) '$(srcdir)/dump-fon.cc'; fi`
-
 dump_indic_data-dump-indic-data.o: dump-indic-data.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dump_indic_data_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dump_indic_data-dump-indic-data.o -MD -MP -MF $(DEPDIR)/dump_indic_data-dump-indic-data.Tpo -c -o dump_indic_data-dump-indic-data.o `test -f 'dump-indic-data.cc' || echo '$(srcdir)/'`dump-indic-data.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/dump_indic_data-dump-indic-data.Tpo $(DEPDIR)/dump_indic_data-dump-indic-data.Po
@@ -2867,6 +2404,62 @@ test_buffer_serialize-test-buffer-serialize.obj: test-buffer-serialize.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_buffer_serialize_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_buffer_serialize-test-buffer-serialize.obj `if test -f 'test-buffer-serialize.cc'; then $(CYGPATH_W) 'test-buffer-serialize.cc'; else $(CYGPATH_W) '$(srcdir)/test-buffer-serialize.cc'; fi`
 
+test_iter-test-iter.o: test-iter.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_iter-test-iter.o -MD -MP -MF $(DEPDIR)/test_iter-test-iter.Tpo -c -o test_iter-test-iter.o `test -f 'test-iter.cc' || echo '$(srcdir)/'`test-iter.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_iter-test-iter.Tpo $(DEPDIR)/test_iter-test-iter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-iter.cc' object='test_iter-test-iter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_iter-test-iter.o `test -f 'test-iter.cc' || echo '$(srcdir)/'`test-iter.cc
+
+test_iter-test-iter.obj: test-iter.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_iter-test-iter.obj -MD -MP -MF $(DEPDIR)/test_iter-test-iter.Tpo -c -o test_iter-test-iter.obj `if test -f 'test-iter.cc'; then $(CYGPATH_W) 'test-iter.cc'; else $(CYGPATH_W) '$(srcdir)/test-iter.cc'; fi`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_iter-test-iter.Tpo $(DEPDIR)/test_iter-test-iter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-iter.cc' object='test_iter-test-iter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_iter-test-iter.obj `if test -f 'test-iter.cc'; then $(CYGPATH_W) 'test-iter.cc'; else $(CYGPATH_W) '$(srcdir)/test-iter.cc'; fi`
+
+test_iter-hb-static.o: hb-static.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_iter-hb-static.o -MD -MP -MF $(DEPDIR)/test_iter-hb-static.Tpo -c -o test_iter-hb-static.o `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_iter-hb-static.Tpo $(DEPDIR)/test_iter-hb-static.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='test_iter-hb-static.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_iter-hb-static.o `test -f 'hb-static.cc' || echo '$(srcdir)/'`hb-static.cc
+
+test_iter-hb-static.obj: hb-static.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_iter-hb-static.obj -MD -MP -MF $(DEPDIR)/test_iter-hb-static.Tpo -c -o test_iter-hb-static.obj `if test -f 'hb-static.cc'; then $(CYGPATH_W) 'hb-static.cc'; else $(CYGPATH_W) '$(srcdir)/hb-static.cc'; fi`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_iter-hb-static.Tpo $(DEPDIR)/test_iter-hb-static.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-static.cc' object='test_iter-hb-static.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_iter_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_iter-hb-static.obj `if test -f 'hb-static.cc'; then $(CYGPATH_W) 'hb-static.cc'; else $(CYGPATH_W) '$(srcdir)/hb-static.cc'; fi`
+
+test_name_table-test-name-table.o: test-name-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_name_table_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_name_table-test-name-table.o -MD -MP -MF $(DEPDIR)/test_name_table-test-name-table.Tpo -c -o test_name_table-test-name-table.o `test -f 'test-name-table.cc' || echo '$(srcdir)/'`test-name-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_name_table-test-name-table.Tpo $(DEPDIR)/test_name_table-test-name-table.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-name-table.cc' object='test_name_table-test-name-table.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_name_table_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_name_table-test-name-table.o `test -f 'test-name-table.cc' || echo '$(srcdir)/'`test-name-table.cc
+
+test_name_table-test-name-table.obj: test-name-table.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_name_table_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_name_table-test-name-table.obj -MD -MP -MF $(DEPDIR)/test_name_table-test-name-table.Tpo -c -o test_name_table-test-name-table.obj `if test -f 'test-name-table.cc'; then $(CYGPATH_W) 'test-name-table.cc'; else $(CYGPATH_W) '$(srcdir)/test-name-table.cc'; fi`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_name_table-test-name-table.Tpo $(DEPDIR)/test_name_table-test-name-table.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-name-table.cc' object='test_name_table-test-name-table.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_name_table_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_name_table-test-name-table.obj `if test -f 'test-name-table.cc'; then $(CYGPATH_W) 'test-name-table.cc'; else $(CYGPATH_W) '$(srcdir)/test-name-table.cc'; fi`
+
+test_ot_color-test-ot-color.o: test-ot-color.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_color_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_ot_color-test-ot-color.o -MD -MP -MF $(DEPDIR)/test_ot_color-test-ot-color.Tpo -c -o test_ot_color-test-ot-color.o `test -f 'test-ot-color.cc' || echo '$(srcdir)/'`test-ot-color.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_ot_color-test-ot-color.Tpo $(DEPDIR)/test_ot_color-test-ot-color.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-ot-color.cc' object='test_ot_color-test-ot-color.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_color_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_ot_color-test-ot-color.o `test -f 'test-ot-color.cc' || echo '$(srcdir)/'`test-ot-color.cc
+
+test_ot_color-test-ot-color.obj: test-ot-color.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_color_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_ot_color-test-ot-color.obj -MD -MP -MF $(DEPDIR)/test_ot_color-test-ot-color.Tpo -c -o test_ot_color-test-ot-color.obj `if test -f 'test-ot-color.cc'; then $(CYGPATH_W) 'test-ot-color.cc'; else $(CYGPATH_W) '$(srcdir)/test-ot-color.cc'; fi`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_ot_color-test-ot-color.Tpo $(DEPDIR)/test_ot_color-test-ot-color.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-ot-color.cc' object='test_ot_color-test-ot-color.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_color_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_ot_color-test-ot-color.obj `if test -f 'test-ot-color.cc'; then $(CYGPATH_W) 'test-ot-color.cc'; else $(CYGPATH_W) '$(srcdir)/test-ot-color.cc'; fi`
+
 test_ot_tag-hb-ot-tag.o: hb-ot-tag.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_tag_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_ot_tag-hb-ot-tag.o -MD -MP -MF $(DEPDIR)/test_ot_tag-hb-ot-tag.Tpo -c -o test_ot_tag-hb-ot-tag.o `test -f 'hb-ot-tag.cc' || echo '$(srcdir)/'`hb-ot-tag.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_ot_tag-hb-ot-tag.Tpo $(DEPDIR)/test_ot_tag-hb-ot-tag.Po
@@ -2895,6 +2488,20 @@ test_size_params-test-size-params.obj: test-size-params.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_size_params_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_size_params-test-size-params.obj `if test -f 'test-size-params.cc'; then $(CYGPATH_W) 'test-size-params.cc'; else $(CYGPATH_W) '$(srcdir)/test-size-params.cc'; fi`
 
+test_unicode_ranges-test-unicode-ranges.o: test-unicode-ranges.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_unicode_ranges_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_unicode_ranges-test-unicode-ranges.o -MD -MP -MF $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Tpo -c -o test_unicode_ranges-test-unicode-ranges.o `test -f 'test-unicode-ranges.cc' || echo '$(srcdir)/'`test-unicode-ranges.cc
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Tpo $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-unicode-ranges.cc' object='test_unicode_ranges-test-unicode-ranges.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_unicode_ranges_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_unicode_ranges-test-unicode-ranges.o `test -f 'test-unicode-ranges.cc' || echo '$(srcdir)/'`test-unicode-ranges.cc
+
+test_unicode_ranges-test-unicode-ranges.obj: test-unicode-ranges.cc
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_unicode_ranges_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_unicode_ranges-test-unicode-ranges.obj -MD -MP -MF $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Tpo -c -o test_unicode_ranges-test-unicode-ranges.obj `if test -f 'test-unicode-ranges.cc'; then $(CYGPATH_W) 'test-unicode-ranges.cc'; else $(CYGPATH_W) '$(srcdir)/test-unicode-ranges.cc'; fi`
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Tpo $(DEPDIR)/test_unicode_ranges-test-unicode-ranges.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='test-unicode-ranges.cc' object='test_unicode_ranges-test-unicode-ranges.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_unicode_ranges_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_unicode_ranges-test-unicode-ranges.obj `if test -f 'test-unicode-ranges.cc'; then $(CYGPATH_W) 'test-unicode-ranges.cc'; else $(CYGPATH_W) '$(srcdir)/test-unicode-ranges.cc'; fi`
+
 test_would_substitute-test-would-substitute.o: test-would-substitute.cc
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_would_substitute_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_would_substitute-test-would-substitute.o -MD -MP -MF $(DEPDIR)/test_would_substitute-test-would-substitute.Tpo -c -o test_would_substitute-test-would-substitute.o `test -f 'test-would-substitute.cc' || echo '$(srcdir)/'`test-would-substitute.cc
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/test_would_substitute-test-would-substitute.Tpo $(DEPDIR)/test_would_substitute-test-would-substitute.Po
@@ -3330,6 +2937,13 @@ check-libstdc++.sh.log: check-libstdc++.sh
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-iter.log: test-iter$(EXEEXT)
+       @p='test-iter$(EXEEXT)'; \
+       b='test-iter'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-ot-tag.log: test-ot-tag$(EXEEXT)
        @p='test-ot-tag$(EXEEXT)'; \
        b='test-ot-tag'; \
@@ -3573,8 +3187,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-cmakeDATA \
 
 
 # Convenience targets:
-lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
-fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
+lib: $(BUILT_SOURCES) libharfbuzz.la
+libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
 @HAVE_UCDN_TRUE@hb-ucdn/libhb-ucdn.la: ucdn
 @HAVE_UCDN_TRUE@ucdn:
 @HAVE_UCDN_TRUE@       @$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
@@ -3608,15 +3222,17 @@ $(srcdir)/hb-version.h: hb-version.h.in $(top_srcdir)/configure.ac
        || ($(RM) "$@"; false)
 check: $(DEF_FILES) # For check-symbols.sh
 harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-subset.def: $(HB_SUBSET_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-icu.def: $(HB_ICU_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
 harfbuzz-gobject.def: $(HB_GOBJECT_headers)
-       $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py "$@"
+       $(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 "$@" $^
 
-unicode-tables: arabic-table indic-table use-table
+unicode-tables: arabic-table indic-table tag-table use-table emoji-table
 
 arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
@@ -3626,13 +3242,25 @@ indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategor
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
        || ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
 
+tag-table: gen-tag-table.py languagetags language-subtag-registry
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
+       || ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
+
 use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
        $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
        || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
 
+vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
+       || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
+
+emoji-table: gen-emoji-table.py emoji-data.txt
+       $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
+       || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
+
 built-sources: $(BUILT_SOURCES)
 
-.PHONY: unicode-tables arabic-table indic-table use-table built-sources
+.PHONY: unicode-tables arabic-table indic-table tag-table use-table vowel-constraints emoji-table built-sources
 # We decided to add ragel-generated files to git...
 #MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
 $(srcdir)/%.hh: $(srcdir)/%.rl
index 0bc9e58..0da4abe 100644 (file)
 # Base and default-included sources and headers
 
 HB_BASE_sources = \
-       hb-atomic-private.hh \
-       hb-blob-private.hh \
+       hb-aat-fdsc-table.hh \
+       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-lcar-table.hh \
+       hb-aat-layout-morx-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-array.hh \
+       hb-atomic.hh \
        hb-blob.cc \
-       hb-buffer-private.hh \
+       hb-blob.hh \
        hb-buffer-serialize.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-debug.hh \
        hb-dsalgs.hh \
-       hb-face-private.hh \
        hb-face.cc \
-       hb-font-private.hh \
+       hb-face.hh \
        hb-font.cc \
-       hb-map-private.hh \
+       hb-font.hh \
+       hb-iter.hh \
+       hb-kern.hh \
+       hb-machinery.hh \
        hb-map.cc \
-       hb-mutex-private.hh \
-       hb-object-private.hh \
-       hb-open-file-private.hh \
-       hb-open-type-private.hh \
-       hb-ot-color-cbdt-table.hh \
+       hb-map.hh \
+       hb-mutex.hh \
+       hb-null.hh \
+       hb-object.hh \
+       hb-open-file.hh \
+       hb-open-type.hh \
+       hb-ot-cff-common.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.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 \
+       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-name-language.cc \
+       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-shape-complex-arabic-fallback.hh \
+       hb-ot-shape-complex-arabic-table.hh \
+       hb-ot-shape-complex-arabic-win1256.hh \
+       hb-ot-shape-complex-arabic.cc \
+       hb-ot-shape-complex-arabic.hh \
+       hb-ot-shape-complex-default.cc \
+       hb-ot-shape-complex-hangul.cc \
+       hb-ot-shape-complex-hebrew.cc \
+       hb-ot-shape-complex-indic-table.cc \
+       hb-ot-shape-complex-indic.cc \
+       hb-ot-shape-complex-indic.hh \
+       hb-ot-shape-complex-khmer.cc \
+       hb-ot-shape-complex-khmer.hh \
+       hb-ot-shape-complex-myanmar.cc \
+       hb-ot-shape-complex-myanmar.hh \
+       hb-ot-shape-complex-thai.cc \
+       hb-ot-shape-complex-use-table.cc \
+       hb-ot-shape-complex-use.cc \
+       hb-ot-shape-complex-use.hh \
+       hb-ot-shape-complex-vowel-constraints.cc \
+       hb-ot-shape-complex-vowel-constraints.hh \
+       hb-ot-shape-complex.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-private.hh \
-       hb-set-digest-private.hh \
-       hb-set-private.hh \
+       hb-ot-var-avar-table.hh \
+       hb-ot-var-fvar-table.hh \
+       hb-ot-var-hvar-table.hh \
+       hb-ot-var-mvar-table.hh \
+       hb-ot-var.cc \
+       hb-ot-vorg-table.hh \
+       hb-set-digest.hh \
        hb-set.cc \
-       hb-shape.cc \
-       hb-shape-plan-private.hh \
+       hb-set.hh \
        hb-shape-plan.cc \
+       hb-shape-plan.hh \
+       hb-shape.cc \
+       hb-shaper-impl.hh \
        hb-shaper-list.hh \
-       hb-shaper-impl-private.hh \
-       hb-shaper-private.hh \
        hb-shaper.cc \
+       hb-shaper.hh \
        hb-static.cc \
        hb-string-array.hh \
-       hb-unicode-private.hh \
+       hb-unicode-emoji-table.hh \
        hb-unicode.cc \
-       hb-utf-private.hh \
+       hb-unicode.hh \
+       hb-utf.hh \
+       hb-vector.hh \
        hb-warning.cc \
+       hb.hh \
        $(NULL)
 
 HB_BASE_RAGEL_GENERATED_sources = \
        hb-buffer-deserialize-json.hh \
        hb-buffer-deserialize-text.hh \
+       hb-ot-shape-complex-indic-machine.hh \
+       hb-ot-shape-complex-khmer-machine.hh \
+       hb-ot-shape-complex-myanmar-machine.hh \
+       hb-ot-shape-complex-use-machine.hh \
        $(NULL)
 HB_BASE_RAGEL_sources = \
        hb-buffer-deserialize-json.rl \
        hb-buffer-deserialize-text.rl \
+       hb-ot-shape-complex-indic-machine.rl \
+       hb-ot-shape-complex-khmer-machine.rl \
+       hb-ot-shape-complex-myanmar-machine.rl \
+       hb-ot-shape-complex-use-machine.rl \
        $(NULL)
 
 HB_BASE_headers = \
-       hb.h \
+       hb-aat-layout.h \
+       hb-aat.h \
        hb-blob.h \
        hb-buffer.h \
        hb-common.h \
@@ -72,106 +175,27 @@ HB_BASE_headers = \
        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-name.h \
+       hb-ot-shape.h \
+       hb-ot-var.h \
+       hb-ot.h \
        hb-set.h \
-       hb-shape.h \
        hb-shape-plan.h \
+       hb-shape.h \
        hb-unicode.h \
        hb-version.h \
+       hb.h \
        $(NULL)
 
 HB_FALLBACK_sources = \
        hb-fallback-shape.cc    \
        $(NULL)
 
-HB_OT_sources = \
-       hb-aat-layout.cc \
-       hb-aat-layout-common-private.hh \
-       hb-aat-layout-ankr-table.hh \
-       hb-aat-layout-bsln-table.hh \
-       hb-aat-layout-feat-table.hh \
-       hb-aat-layout-kerx-table.hh \
-       hb-aat-layout-morx-table.hh \
-       hb-aat-layout-trak-table.hh \
-       hb-aat-layout-private.hh \
-       hb-aat-fmtx-table.hh \
-       hb-aat-gcid-table.hh \
-       hb-aat-ltag-table.hh \
-       hb-ot-font.cc \
-       hb-ot-layout.cc \
-       hb-ot-layout-base-table.hh \
-       hb-ot-layout-common-private.hh \
-       hb-ot-layout-gdef-table.hh \
-       hb-ot-layout-gpos-table.hh \
-       hb-ot-layout-gsubgpos-private.hh \
-       hb-ot-layout-gsub-table.hh \
-       hb-ot-layout-jstf-table.hh \
-       hb-ot-layout-private.hh \
-       hb-ot-color.cc \
-       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-map.cc \
-       hb-ot-map-private.hh \
-       hb-ot-math.cc \
-       hb-ot-math-table.hh \
-       hb-ot-shape.cc \
-       hb-ot-shape-complex-arabic.cc \
-       hb-ot-shape-complex-arabic-fallback.hh \
-       hb-ot-shape-complex-arabic-private.hh \
-       hb-ot-shape-complex-arabic-table.hh \
-       hb-ot-shape-complex-arabic-win1256.hh \
-       hb-ot-shape-complex-default.cc \
-       hb-ot-shape-complex-hangul.cc \
-       hb-ot-shape-complex-hebrew.cc \
-       hb-ot-shape-complex-indic.cc \
-       hb-ot-shape-complex-indic-private.hh \
-       hb-ot-shape-complex-indic-table.cc \
-       hb-ot-shape-complex-khmer-private.hh \
-       hb-ot-shape-complex-khmer.cc \
-       hb-ot-shape-complex-myanmar-private.hh \
-       hb-ot-shape-complex-myanmar.cc \
-       hb-ot-shape-complex-thai.cc \
-       hb-ot-shape-complex-tibetan.cc \
-       hb-ot-shape-complex-use.cc \
-       hb-ot-shape-complex-use-private.hh \
-       hb-ot-shape-complex-use-table.cc \
-       hb-ot-shape-complex-private.hh \
-       hb-ot-shape-normalize-private.hh \
-       hb-ot-shape-normalize.cc \
-       hb-ot-shape-fallback-private.hh \
-       hb-ot-shape-fallback.cc \
-       hb-ot-shape-private.hh \
-       hb-ot-var.cc \
-       hb-ot-var-avar-table.hh \
-       hb-ot-var-fvar-table.hh \
-       hb-ot-var-hvar-table.hh \
-       hb-ot-var-mvar-table.hh \
-       $(NULL)
-
-HB_OT_RAGEL_GENERATED_sources = \
-       hb-ot-shape-complex-indic-machine.hh \
-       hb-ot-shape-complex-khmer-machine.hh \
-       hb-ot-shape-complex-myanmar-machine.hh \
-       hb-ot-shape-complex-use-machine.hh \
-       $(NULL)
-HB_OT_RAGEL_sources = \
-       hb-ot-shape-complex-indic-machine.rl \
-       hb-ot-shape-complex-khmer-machine.rl \
-       hb-ot-shape-complex-myanmar-machine.rl \
-       hb-ot-shape-complex-use-machine.rl \
-       $(NULL)
-
-HB_OT_headers = \
-       hb-ot.h \
-       hb-ot-font.h \
-       hb-ot-layout.h \
-       hb-ot-math.h \
-       hb-ot-shape.h \
-       hb-ot-tag.h \
-       hb-ot-var.h \
-       $(NULL)
-
 # Optional Sources and Headers with external deps
 
 HB_FT_sources = hb-ft.cc
@@ -203,18 +227,30 @@ HB_ICU_headers = hb-icu.h
 
 # Sources for libharfbuzz-subset
 HB_SUBSET_sources = \
+       hb-ot-cff1-table.cc \
+       hb-ot-cff2-table.cc \
        hb-static.cc \
-       hb-subset.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-glyf.cc \
+       hb-subset-glyf.hh \
+       hb-subset-glyf.hh \
        hb-subset-input.cc \
+       hb-subset-input.hh \
        hb-subset-plan.cc \
+       hb-subset-plan.hh \
+       hb-subset-plan.hh \
+       hb-subset.cc \
+       hb-subset.hh \
+       hb-subset.hh \
        $(NULL)
 
 HB_SUBSET_headers = \
        hb-subset.h \
-       hb-subset-glyf.hh \
-       hb-subset-plan.hh \
-       hb-subset-private.hh \
        $(NULL)
 
 HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
index fd565da..f938f70 100755 (executable)
@@ -23,14 +23,14 @@ grep -v 'hb[.]h:' |
 grep . >&2 && stat=1
 
 
-echo 'Checking that source files #include "hb-*private.hh" first (or none)'
+echo 'Checking that source files #include a private header first (or none)'
 
 for x in $HBSOURCES; do
        test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
-       grep '#.*\<include\>' "$x" /dev/null | grep -v 'include _' | head -n 1
+       grep '#.*\<include\>' "$x" /dev/null | head -n 1
 done |
-grep -v '"hb-.*private[.]hh"' |
-grep -v 'hb-private[.]hh:' |
+grep -v '"hb-.*[.]hh"' |
+grep -v 'hb[.]hh' |
 grep . >&2 && stat=1
 
 
index 71551cb..def25c7 100755 (executable)
@@ -7,7 +7,6 @@ test -z "$srcdir" && srcdir=.
 test -z "$libs" && libs=.libs
 stat=0
 
-
 if which objdump 2>/dev/null >/dev/null; then
        :
 else
@@ -31,7 +30,8 @@ done
 
 echo "Checking that no object file has lazy static C++ constructors/destructors or other such stuff"
 for obj in $OBJS; do
-       if objdump -t "$obj" | grep '__cxa_'; then
+       if objdump -t "$obj" | grep -q '__cxa_' && ! objdump -t "$obj" | grep -q __ubsan_handle; then
+               objdump -t "$obj" | grep '__cxa_'
                echo "Ouch, $obj has lazy static C++ constructors/destructors or other such stuff"
                stat=1
        fi
index d4eca50..cea8684 100755 (executable)
@@ -26,7 +26,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
                symprefix=
                if test $suffix = dylib; then symprefix=_; fi
 
-               EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`"
+               EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`"
 
                prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
 
diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc
deleted file mode 100644 (file)
index 99e8ef9..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  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.
- */
-
-#include "hb-static.cc"
-#include "hb-ot-color-cbdt-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
-
-#include "hb-ft.h"
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_GLYPH_H
-
-#include <cairo.h>
-#include <cairo-ft.h>
-#include <cairo-svg.h>
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-void cbdt_callback (const uint8_t* data, unsigned int length,
-                    unsigned int group, unsigned int gid)
-{
-  char output_path[255];
-  sprintf (output_path, "out/cbdt-%d-%d.png", group, gid);
-  FILE *f = fopen (output_path, "wb");
-  fwrite (data, 1, length, f);
-  fclose (f);
-}
-
-void sbix_callback (const uint8_t* data, unsigned int length,
-                    unsigned int group, unsigned int gid)
-{
-  char output_path[255];
-  sprintf (output_path, "out/sbix-%d-%d.png", group, gid);
-  FILE *f = fopen (output_path, "wb");
-  fwrite (data, 1, length, f);
-  fclose (f);
-}
-
-void svg_callback (const uint8_t* data, unsigned int length,
-                   unsigned int start_glyph, unsigned int end_glyph)
-{
-  char output_path[255];
-  if (start_glyph == end_glyph)
-    sprintf (output_path, "out/svg-%d.svg", start_glyph);
-  else
-    sprintf (output_path, "out/svg-%d-%d.svg", start_glyph, end_glyph);
-
-  // append "z" if the content is gzipped
-  if ((data[0] == 0x1F) && (data[1] == 0x8B))
-    strcat (output_path, "z");
-
-  FILE *f = fopen (output_path, "wb");
-  fwrite (data, 1, length, f);
-  fclose (f);
-}
-
-void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upem, unsigned int num_glyphs,
-                         const OT::COLR *colr, const OT::CPAL *cpal)
-{
-  for (unsigned int i = 0; i < num_glyphs; ++i)
-  {
-    unsigned int first_layer_index, num_layers;
-    if (colr->get_base_glyph_record (i, &first_layer_index, &num_layers))
-    {
-      // Measure
-      cairo_text_extents_t extents;
-      {
-       cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-       cairo_t *cr = cairo_create (surface);
-       cairo_set_font_face (cr, cairo_face);
-       cairo_set_font_size (cr, upem);
-
-       cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
-       for (unsigned int j = 0; j < num_layers; ++j)
-       {
-         hb_codepoint_t glyph_id;
-         unsigned int color_index;
-         colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
-         glyphs[j].index = glyph_id;
-       }
-       cairo_glyph_extents (cr, glyphs, num_layers, &extents);
-       free (glyphs);
-       cairo_surface_destroy (surface);
-       cairo_destroy (cr);
-      }
-
-      // Add a slight margin
-      extents.width += extents.width / 10;
-      extents.height += extents.height / 10;
-      extents.x_bearing -= extents.width / 20;
-      extents.y_bearing -= extents.height / 20;
-
-      // Render
-      unsigned int pallet_count = cpal->get_palette_count ();
-      for (unsigned int pallet = 0; pallet < pallet_count; ++pallet) {
-       char output_path[255];
-
-       // If we have more than one pallet, use a better namin
-       if (pallet_count == 1)
-         sprintf (output_path, "out/colr-%d.svg", i);
-       else
-         sprintf (output_path, "out/colr-%d-%d.svg", i, pallet);
-
-       cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
-       cairo_t *cr = cairo_create (surface);
-       cairo_set_font_face (cr, cairo_face);
-       cairo_set_font_size (cr, upem);
-
-       for (unsigned int j = 0; j < num_layers; ++j)
-       {
-         hb_codepoint_t glyph_id;
-         unsigned int color_index;
-         colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
-
-         uint32_t color = cpal->get_color_record_argb (color_index, pallet);
-         int alpha = color & 0xFF;
-         int r = (color >> 8) & 0xFF;
-         int g = (color >> 16) & 0xFF;
-         int b = (color >> 24) & 0xFF;
-         cairo_set_source_rgba (cr, r / 255.f, g / 255.f, b / 255.f, alpha);
-
-         cairo_glyph_t glyph;
-         glyph.index = glyph_id;
-         glyph.x = -extents.x_bearing;
-         glyph.y = -extents.y_bearing;
-         cairo_show_glyphs (cr, &glyph, 1);
-       }
-
-       cairo_surface_destroy (surface);
-       cairo_destroy (cr);
-      }
-    }
-  }
-}
-
-void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, unsigned int num_glyphs)
-{
-  // Dump every glyph available on the font
-  return; // disabled for now
-  for (unsigned int i = 0; i < num_glyphs; ++i)
-  {
-    cairo_text_extents_t extents;
-    cairo_glyph_t glyph = {0};
-    glyph.index = i;
-
-    // Measure
-    {
-      cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-      cairo_t *cr = cairo_create (surface);
-      cairo_set_font_face (cr, cairo_face);
-      cairo_set_font_size (cr, upem);
-
-      cairo_glyph_extents (cr, &glyph, 1, &extents);
-      cairo_surface_destroy (surface);
-      cairo_destroy (cr);
-    }
-
-    // Add a slight margin
-    extents.width += extents.width / 10;
-    extents.height += extents.height / 10;
-    extents.x_bearing -= extents.width / 20;
-    extents.y_bearing -= extents.height / 20;
-
-    // Render
-    {
-      char output_path[255];
-      sprintf (output_path, "out/%d.svg", i);
-      cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
-      cairo_t *cr = cairo_create (surface);
-      cairo_set_font_face (cr, cairo_face);
-      cairo_set_font_size (cr, upem);
-      glyph.x = -extents.x_bearing;
-      glyph.y = -extents.y_bearing;
-      cairo_show_glyphs (cr, &glyph, 1);
-      cairo_surface_destroy (surface);
-      cairo_destroy (cr);
-    }
-  }
-}
-
-int main (int argc, char **argv)
-{
-  if (argc != 2) {
-    fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
-    exit (1);
-  }
-
-  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-  hb_face_t *face = hb_face_create (blob, 0);
-  hb_font_t *font = hb_font_create (face);
-
-  OT::CBDT::accelerator_t cbdt;
-  cbdt.init (face);
-  cbdt.dump (cbdt_callback);
-  cbdt.fini ();
-
-  OT::sbix::accelerator_t sbix;
-  sbix.init (face);
-  sbix.dump (sbix_callback);
-  sbix.fini ();
-
-  OT::SVG::accelerator_t svg;
-  svg.init (face);
-  svg.dump (svg_callback);
-  svg.fini ();
-
-  OT::Sanitizer<OT::COLR> sanitizerCOLR;
-  hb_blob_t* colr_blob = sanitizerCOLR.sanitize (face->reference_table (HB_OT_TAG_COLR));
-  const OT::COLR *colr = colr_blob->as<OT::COLR> ();
-
-  OT::Sanitizer<OT::CPAL> sanitizerCPAL;
-  hb_blob_t* cpal_blob = sanitizerCPAL.sanitize (face->reference_table (HB_OT_TAG_CPAL));
-  const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
-
-  cairo_font_face_t *cairo_face;
-  {
-    FT_Library library;
-    FT_Init_FreeType (&library);
-    FT_Face ftface;
-    FT_New_Face (library, argv[1], 0, &ftface);
-    cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0);
-  }
-  unsigned int num_glyphs = hb_face_get_glyph_count (face);
-  unsigned int upem = hb_face_get_upem (face);
-  colr_cpal_rendering (cairo_face, upem, num_glyphs, colr, cpal);
-  dump_glyphs (cairo_face, upem, num_glyphs);
-
-
-  hb_font_destroy (font);
-  hb_face_destroy (face);
-  hb_blob_destroy (blob);
-
-  return 0;
-}
diff --git a/src/dump-fon.cc b/src/dump-fon.cc
deleted file mode 100644 (file)
index 4015409..0000000
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  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.
- */
-
-#include "hb-static.cc"
-#include <stdio.h>
-#include <stdlib.h>
-#include "hb-open-type-private.hh"
-
-template <typename Type, int Bytes> struct LEInt;
-
-template <typename Type>
-struct LEInt<Type, 1>
-{
-  public:
-  inline void set (Type V)
-  {
-    v = V;
-  }
-  inline operator Type (void) const
-  {
-    return v;
-  }
-  private: uint8_t v;
-};
-template <typename Type>
-struct LEInt<Type, 2>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[1] = (V >>  8) & 0xFF;
-    v[0] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[1] <<  8)
-         + (v[0]      );
-  }
-  private: uint8_t v[2];
-};
-template <typename Type>
-struct LEInt<Type, 3>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[2] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[0] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[2] << 16)
-         + (v[1] <<  8)
-         + (v[0]      );
-  }
-  private: uint8_t v[3];
-};
-template <typename Type>
-struct LEInt<Type, 4>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[3] = (V >> 24) & 0xFF;
-    v[2] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[0] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[3] << 24)
-         + (v[2] << 16)
-         + (v[1] <<  8)
-         + (v[0]      );
-  }
-  private: uint8_t v[4];
-};
-
-template <typename Type, unsigned int Size>
-struct LEIntType
-{
-  inline void set (Type i) { v.set (i); }
-  inline operator Type(void) const { return v; }
-  inline bool sanitize (OT::hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  LEInt<Type, Size> v;
-  public:
-  DEFINE_SIZE_STATIC (Size);
-};
-
-typedef LEIntType<uint8_t,  1> LEUINT8;                /* 8-bit unsigned integer. */
-typedef LEIntType<int8_t,   1> LEINT8;         /* 8-bit signed integer. */
-typedef LEIntType<uint16_t, 2> LEUINT16;       /* 16-bit unsigned integer. */
-typedef LEIntType<int16_t,  2> LEINT16;                /* 16-bit signed integer. */
-typedef LEIntType<uint32_t, 4> LEUINT32;       /* 32-bit unsigned integer. */
-typedef LEIntType<int32_t,  4> LEINT32;                /* 32-bit signed integer. */
-typedef LEIntType<uint32_t, 3> LEUINT24;       /* 24-bit unsigned integer. */
-
-
-struct LE_FONTINFO16
-{
-  inline bool sanitize (OT::hb_sanitize_context_t *c, unsigned int length) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && c->check_range (this, length)));
-  }
-
-  // https://msdn.microsoft.com/en-us/library/cc194829.aspx
-  enum charset_t
-  {
-    // dfCharSet possible values and the codepage they are indicating to
-    ANSI       = 0x00, // 1252
-    DEFAULT    = 0x01, //
-    SYMBOL     = 0x02, //
-    SHIFTJIS   = 0x80, // 932
-    HANGUL     = 0x81, // 949
-    GB2312     = 0x86, // 936
-    CHINESEBIG5        = 0x88, // 950
-    GREEK      = 0xA1, // 1253
-    TURKISH    = 0xA2, // 1254
-    HEBREW     = 0xB1, // 1255
-    ARABIC     = 0xB2, // 1256
-    BALTIC     = 0xBA, // 1257
-    RUSSIAN    = 0xCC, // 1251
-    THAI       = 0xDE, // 874
-    EE         = 0xEE, // 1250
-    OEM                = 0xFF  //
-  };
-
-  inline const char* get_charset() const
-  {
-    switch (dfCharSet) {
-    case ANSI: return "ISO8859";
-    case DEFAULT: return "WinDefault";
-    case SYMBOL: return "Symbol";
-    case SHIFTJIS: return "JISX0208.1983";
-    case HANGUL: return "MSHangul";
-    case GB2312: return "GB2312.1980";
-    case CHINESEBIG5: return "Big5";
-    case GREEK: return "CP1253";
-    case TURKISH: return "CP1254";
-    case HEBREW: return "CP1255";
-    case ARABIC: return "CP1256";
-    case BALTIC: return "CP1257";
-    case RUSSIAN: return "CP1251";
-    case THAI: return "CP874";
-    case EE: return "CP1250";
-    case OEM: return "OEM";
-    default: return "Unknown";
-    }
-  }
-
-  inline unsigned int get_version () const
-  {
-    return dfVersion;
-  }
-
-  inline unsigned int get_weight () const
-  {
-    return dfWeight;
-  }
-
-  enum weight_t {
-    DONTCARE   = 0,
-    THIN       = 100,
-    EXTRALIGHT = 200,
-    ULTRALIGHT = 200,
-    LIGHT      = 300,
-    NORMAL     = 400,
-    REGULAR    = 400,
-    MEDIUM     = 500,
-    SEMIBOLD   = 600,
-    DEMIBOLD   = 600,
-    BOLD       = 700,
-    EXTRABOLD  = 800,
-    ULTRABOLD  = 800,
-    HEAVY      = 900,
-    BLACK      = 900
-  };
-
-  inline void dump () const
-  {
-    // With https://github.com/juanitogan/mkwinfont/blob/master/python/dewinfont.py help
-    // Should be implemented differently eventually, but for now
-    unsigned int ctstart;
-    unsigned int ctsize;
-    if (dfVersion == 0x200)
-    {
-      ctstart = 0x76;
-      ctsize = 4;
-    }
-    else
-    {
-      return; // must of ".fon"s are version 2 and even dewinfont V1 implmentation doesn't seem correct
-      ctstart = 0x94;
-      ctsize = 6;
-    }
-    // unsigned int maxwidth = 0;
-    for (unsigned int i = dfFirstChar; i < dfLastChar; ++i)
-    {
-      unsigned int entry = ctstart + ctsize * (i-dfFirstChar);
-      unsigned int w = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry);
-
-      unsigned int off;
-      if (ctsize == 4)
-        off = (uint16_t) OT::StructAtOffset<LEUINT16> (this, entry+2);
-      else
-        off = (uint32_t) OT::StructAtOffset<LEUINT32> (this, entry+2);
-
-      unsigned int widthbytes = (w + 7) / 8;
-      for (unsigned int j = 0; j < dfPixHeight; ++j)
-      {
-        for (unsigned int k = 0; k < widthbytes; ++k)
-       {
-         unsigned int bytepos = off + k * dfPixHeight + j;
-         const uint8_t b = (uint8_t) OT::StructAtOffset<LEINT8> (this, bytepos);
-         for (unsigned int a = 128; a > 0; a >>= 1)
-           printf (b & a ? "x" : ".");
-       }
-       printf ("\n");
-      }
-      printf ("\n\n");
-    }
-  }
-
-  protected:
-  LEUINT16     dfVersion;
-  LEUINT32     dfSize;
-  LEUINT8      dfCopyright[60];
-  LEUINT16     dfType;
-  LEUINT16     dfPoints;
-  LEUINT16     dfVertRes;
-  LEUINT16     dfHorizRes;
-  LEUINT16     dfAscent;
-  LEUINT16     dfInternalLeading;
-  LEUINT16     dfExternalLeading;
-  LEUINT8      dfItalic;
-  LEUINT8      dfUnderline;
-  LEUINT8      dfStrikeOut;
-  LEUINT16     dfWeight; // see weight_t
-  LEUINT8      dfCharSet;  // see charset_t
-  LEUINT16     dfPixWidth;
-  LEUINT16     dfPixHeight;
-  LEUINT8      dfPitchAndFamily;
-  LEUINT16     dfAvgWidth;
-  LEUINT16     dfMaxWidth;
-  LEUINT8      dfFirstChar;
-  LEUINT8      dfLastChar;
-  LEUINT8      dfDefaultChar;
-  LEUINT8      dfBreakChar;
-  LEUINT16     dfWidthBytes;
-  LEUINT32     dfDevice;
-  LEUINT32     dfFace;
-  LEUINT32     dfBitsPointer;
-  LEUINT32     dfBitsOffset;
-  LEUINT8      dfReserved;
-//   LEUINT32  dfFlags;
-//   LEUINT16  dfAspace;
-//   LEUINT16  dfBspace;
-//   LEUINT16  dfCspace;
-//   LEUINT32  dfColorPointer;
-//   LEUINT32  dfReserved1[4];
-  OT::UnsizedArrayOf<LEUINT8>
-               dataZ;
-  public:
-  DEFINE_SIZE_ARRAY (118, dataZ);
-};
-
-struct NE_NAMEINFO
-{
-  friend struct NE_TYPEINFO;
-
-  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         get_font (base, shift).sanitize (c, length << shift)));
-  }
-
-  inline const LE_FONTINFO16& get_font (const void *base, int shift) const
-  {
-    return OT::StructAtOffset<LE_FONTINFO16> (base, offset << shift);
-  }
-
-  enum resource_type_flag_t {
-    NONE     = 0x0000,
-    MOVEABLE = 0x0010,
-    PURE     = 0x0020,
-    PRELOAD  = 0x0040
-  };
-
-  protected:
-  LEUINT16     offset; // Should be shifted with alignmentShiftCount before use
-  LEUINT16     length; // Should be shifted with alignmentShiftCount before use
-  LEUINT16     flags;  // resource_type_flag_t
-  LEUINT16     id;
-  LEUINT16     handle;
-  LEUINT16     usage;
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct NE_TYPEINFO
-{
-  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base, unsigned int shift) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && resources.sanitize (c, count, base, shift));
-  }
-
-  inline unsigned int get_size (void) const
-  { return 8 + count * NE_NAMEINFO::static_size; }
-
-  inline const NE_TYPEINFO& next () const
-  {
-    const NE_TYPEINFO& next = OT::StructAfter<NE_TYPEINFO> (*this);
-    if (type_id == 0)
-      return Null(NE_TYPEINFO);
-    return next;
-  }
-
-  inline const LE_FONTINFO16& get_font (unsigned int idx, const void *base, int shift) const
-  {
-    if (idx < count)
-      return resources[idx].get_font (base, shift);
-    return Null(LE_FONTINFO16);
-  }
-
-  inline unsigned int get_count () const
-  {
-    return count;
-  }
-
-  inline unsigned int get_type_id () const
-  {
-    return type_id;
-  }
-
-  enum type_id_t {
-    CURSOR             = 0x8001,
-    BITMAP             = 0x8002,
-    ICON               = 0x8003,
-    MENU               = 0x8004,
-    DIALOG             = 0x8005,
-    STRING             = 0x8006,
-    FONT_DIRECTORY     = 0x8007,
-    FONT               = 0x8008,
-    ACCELERATOR_TABLE  = 0x8009,
-    RESOURCE_DATA      = 0x800a,
-    GROUP_CURSOR       = 0x800c,
-    GROUP_ICON         = 0x800e,
-    VERSION            = 0x8010
-  };
-
-  protected:
-  LEUINT16     type_id; // see type_id_t
-  LEUINT16     count;
-  LEUINT32     resloader;
-  OT::UnsizedArrayOf<NE_NAMEINFO>
-               resources;
-  public:
-  DEFINE_SIZE_ARRAY (8, resources);
-};
-
-struct NE_RESOURCE_TABLE
-{
-  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-
-    if (!c->check_struct (this))
-      return_trace (false);
-
-    const NE_TYPEINFO* n = &chain;
-    while (n != &Null(NE_TYPEINFO) && c->check_struct (n) && n->get_type_id () != 0)
-    {
-      if (n->get_type_id () == NE_TYPEINFO::FONT)
-       return_trace (n->sanitize (c, base, alignmentShiftCount));
-      n = &n->next();
-    }
-    return_trace (false);
-  }
-
-  inline unsigned int get_shift_value () const
-  {
-    return alignmentShiftCount;
-  }
-
-  inline const NE_TYPEINFO& get_fonts_entry () const
-  {
-    const NE_TYPEINFO* n = &chain;
-    while (n != &Null(NE_TYPEINFO) && n->get_type_id () != 0)
-    {
-      if (n->get_type_id () == NE_TYPEINFO::FONT)
-       return *n;
-      n = &n->next();
-    }
-    return Null(NE_TYPEINFO);
-  }
-
-  protected:
-  LEUINT16     alignmentShiftCount;
-  NE_TYPEINFO  chain;
-  // It is followed by an array of OT::ArrayOf<LEUINT8, LEUINT8> chars;
-  public:
-  DEFINE_SIZE_MIN (2);
-};
-
-// https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L2467
-struct LE_IMAGE_OS2_HEADER
-{
-  inline bool sanitize (OT::hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && (this+rsrctab).sanitize (c, base)));
-  }
-
-  inline const NE_RESOURCE_TABLE& get_resource_table () const
-  {
-    if (magic != 0x454E) // Only NE containers are support for now, NE == 0x454E
-      return Null(NE_RESOURCE_TABLE);
-    return this+rsrctab;
-  }
-
-  protected:
-  LEUINT16     magic;          /* 00 NE signature 'NE' */
-  LEUINT8      ver;            /* 02 Linker version number */
-  LEUINT8      rev;            /* 03 Linker revision number */
-  LEUINT16     enttab;         /* 04 Offset to entry table relative to NE */
-  LEUINT16     cbenttab;       /* 06 Length of entry table in bytes */
-  LEUINT32     crc;            /* 08 Checksum */
-  LEUINT16     flags;          /* 0c Flags about segments in this file */
-  LEUINT16     autodata;       /* 0e Automatic data segment number */
-  LEUINT16     heap;           /* 10 Initial size of local heap */
-  LEUINT16     stack;          /* 12 Initial size of stack */
-  LEUINT32     csip;           /* 14 Initial CS:IP */
-  LEUINT32     sssp;           /* 18 Initial SS:SP */
-  LEUINT16     cseg;           /* 1c # of entries in segment table */
-  LEUINT16     cmod;           /* 1e # of entries in module reference tab. */
-  LEUINT16     cbnrestab;      /* 20 Length of nonresident-name table     */
-  LEUINT16     segtab;         /* 22 Offset to segment table */
-  OT::OffsetTo<NE_RESOURCE_TABLE, LEUINT16>
-               rsrctab;        /* 24 Offset to resource table */
-  LEUINT16     restab;         /* 26 Offset to resident-name table */
-  LEUINT16     modtab;         /* 28 Offset to module reference table */
-  LEUINT16     imptab;         /* 2a Offset to imported name table */
-  LEUINT32     nrestab;        /* 2c Offset to nonresident-name table */
-  LEUINT16     cmovent;        /* 30 # of movable entry points */
-  LEUINT16     align;          /* 32 Logical sector alignment shift count */
-  LEUINT16     cres;           /* 34 # of resource segments */
-  LEUINT8      exetyp;         /* 36 Flags indicating target OS */
-  LEUINT8      flagsothers;    /* 37 Additional information flags */
-  LEUINT16     pretthunks;     /* 38 Offset to return thunks */
-  LEUINT16     psegrefbytes;   /* 3a Offset to segment ref. bytes */
-  LEUINT16     swaparea;       /* 3c Reserved by Microsoft */
-  LEUINT16     expver;         /* 3e Expected Windows version number */
-  public:
-  DEFINE_SIZE_STATIC (64);
-};
-
-struct LE_IMAGE_DOS_HEADER {
-  inline bool sanitize (OT::hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         get_os2_header ().sanitize (c, this)));
-  }
-
-  inline const LE_IMAGE_OS2_HEADER& get_os2_header () const
-  {
-    return this+e_lfanew;
-  }
-
-  protected:
-  LEUINT16     e_magic;        // Magic number
-  LEUINT16     e_cblp;         // Bytes on last page of file
-  LEUINT16     e_cp;           // Pages in file
-  LEUINT16     e_crlc;         // Relocations
-  LEUINT16     e_cparhdr;      // Size of header in paragraphs
-  LEUINT16     e_minalloc;     // Minimum extra paragraphs needed
-  LEUINT16     e_maxalloc;     // Maximum extra paragraphs needed
-  LEUINT16     e_ss;           // Initial (relative) SS value
-  LEUINT16     e_sp;           // Initial SP value
-  LEUINT16     e_csum;         // Checksum
-  LEUINT16     e_ip;           // Initial IP value
-  LEUINT16     e_cs;           // Initial (relative) CS value
-  LEUINT16     e_lfarlc;       // File address of relocation table
-  LEUINT16     e_ovno;         // Overlay number
-  LEUINT16     e_res_0;        // Reserved words
-  LEUINT16     e_res_1;        // Reserved words
-  LEUINT16     e_res_2;        // Reserved words
-  LEUINT16     e_res_3;        // Reserved words
-  LEUINT16     e_oemid;        // OEM identifier (for e_oeminfo)
-  LEUINT16     e_oeminfo;      // OEM information; e_oemid specific
-  LEUINT16     e_res2_0;       // Reserved words
-  LEUINT16     e_res2_1;       // Reserved words
-  LEUINT16     e_res2_2;       // Reserved words
-  LEUINT16     e_res2_3;       // Reserved words
-  LEUINT16     e_res2_4;       // Reserved words
-  LEUINT16     e_res2_5;       // Reserved words
-  LEUINT16     e_res2_6;       // Reserved words
-  LEUINT16     e_res2_7;       // Reserved words
-  LEUINT16     e_res2_8;       // Reserved words
-  LEUINT16     e_res2_9;       // Reserved words
-  OT::OffsetTo<LE_IMAGE_OS2_HEADER, LEUINT32>
-               e_lfanew;       // File address of new exe header
-  public:
-  DEFINE_SIZE_STATIC (64);
-};
-
-int main (int argc, char** argv) {
-  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-
-  OT::Sanitizer<LE_IMAGE_DOS_HEADER> sanitizer;
-  hb_blob_t *font_blob = sanitizer.sanitize (blob);
-  const LE_IMAGE_DOS_HEADER* dos_header = font_blob->as<LE_IMAGE_DOS_HEADER> ();
-
-  const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
-  int shift = rtable.get_shift_value ();
-  const NE_TYPEINFO& entry = rtable.get_fonts_entry ();
-  for (unsigned int i = 0; i < entry.get_count (); ++i)
-  {
-    const LE_FONTINFO16& font = entry.get_font (i, dos_header, shift);
-    printf ("version: %x, weight: %d, charset: %s\n", font.get_version (),
-           font.get_weight (), font.get_charset ());
-    // font.dump ();
-  }
-  return 0;
-}
index d574138..8ddc9d5 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
 
 int
-main (void)
+main ()
 {
   for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
   {
index 7dd09b2..cffbb92 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-khmer-private.hh"
+#include "hb-ot-shape-complex-khmer.hh"
 
 int
-main (void)
+main ()
 {
   for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
   {
     hb_glyph_info_t info;
     info.codepoint = u;
     set_khmer_properties (info);
-    if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
-       info.khmer_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
-      printf("U+%04X   %u      %u\n", u,
-            info.khmer_category(),
-            info.khmer_position());
+    if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER)
+      printf("U+%04X   %u\n", u,
+            info.khmer_category());
   }
 }
index 2df9cd9..c1a303f 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-myanmar-private.hh"
+#include "hb-ot-shape-complex-myanmar.hh"
 
 int
-main (void)
+main ()
 {
   for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
   {
index 0e64688..d639426 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
+#include "hb-ot-shape-complex-use.hh"
 
 int
-main (void)
+main ()
 {
   for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
   {
index 9a997d6..9111c69 100755 (executable)
@@ -4,16 +4,21 @@ from __future__ import print_function, division, absolute_import
 
 import io, os, re, sys
 
+if len (sys.argv) < 3:
+       sys.exit("usage: gen-def.py harfbuzz.def hb.h [hb-blob.h hb-buffer.h ...]")
+
+output_file = sys.argv[1]
+header_paths = sys.argv[2:]
+
 headers_content = []
-for h in os.environ["headers"].split (' '):
+for h in header_paths:
        if h.endswith (".h"):
                with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ())
 
-result = """EXPORTS
+symbols = "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M)))
+
+result = symbols if os.environ.get('PLAIN_LIST', '') else """EXPORTS
 %s
-LIBRARY lib%s-0.dll""" % (
-       "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))),
-       sys.argv[1].replace ('.def', '')
-)
+LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('.def', ''))
 
-with open (sys.argv[1], "w") as f: f.write (result)
+with open (output_file, "w") as f: f.write (result)
diff --git a/src/gen-emoji-table.py b/src/gen-emoji-table.py
new file mode 100755 (executable)
index 0000000..9afe747
--- /dev/null
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+
+from __future__ import print_function, division, absolute_import
+import sys
+import os.path
+from collections import OrderedDict
+
+if len (sys.argv) != 2:
+       print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
+       sys.exit (1)
+
+f = open(sys.argv[1])
+header = [f.readline () for _ in range(10)]
+
+ranges = OrderedDict()
+for line in f.readlines():
+       line = line.strip()
+       if not line or line[0] == '#':
+               continue
+       rang, typ = [s.strip() for s in line.split('#')[0].split(';')[:2]]
+
+       rang = [int(s, 16) for s in rang.split('..')]
+       if len(rang) > 1:
+               start, end = rang
+       else:
+               start = end = rang[0]
+
+       if typ not in ranges:
+               ranges[typ] = []
+       if ranges[typ] and ranges[typ][-1][1] == start - 1:
+               ranges[typ][-1] = (ranges[typ][-1][0], end)
+       else:
+               ranges[typ].append((start, end))
+
+
+
+print ("/* == Start of generated table == */")
+print ("/*")
+print (" * The following tables are generated by running:")
+print (" *")
+print (" *   ./gen-emoji-table.py emoji-data.txt")
+print (" *")
+print (" * on file with this header:")
+print (" *")
+for l in header:
+       print (" * %s" % (l.strip()))
+print (" */")
+print ()
+print ("#ifndef HB_UNICODE_EMOJI_TABLE_HH")
+print ("#define HB_UNICODE_EMOJI_TABLE_HH")
+print ()
+print ('#include "hb-unicode.hh"')
+print ()
+
+for typ,s in ranges.items():
+       if typ != "Extended_Pictographic": continue
+       print()
+       print("static const struct hb_unicode_range_t _hb_unicode_emoji_%s_table[] =" % typ)
+       print("{")
+       for pair in sorted(s):
+               print("  {0x%04X, 0x%04X}," % pair)
+       print("};")
+
+print ()
+print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */")
+print ()
+print ("/* == End of generated table == */")
index 6252664..6532ee7 100755 (executable)
@@ -102,7 +102,7 @@ for h in headers:
                print (" * %s" % (l.strip()))
 print (" */")
 print ()
-print ('#include "hb-ot-shape-complex-indic-private.hh"')
+print ('#include "hb-ot-shape-complex-indic.hh"')
 print ()
 
 # Shorten values
@@ -131,6 +131,8 @@ for i in range (2):
 
 what = ["INDIC_SYLLABIC_CATEGORY", "INDIC_MATRA_CATEGORY"]
 what_short = ["ISC", "IMC"]
+print ('#pragma GCC diagnostic push')
+print ('#pragma GCC diagnostic ignored "-Wunused-macros"')
 for i in range (2):
        print ()
        vv = sorted (values[i].keys ())
@@ -148,6 +150,7 @@ for i in range (2):
                        (what_short[i], s, what[i], v.upper (),
                        '       '* ((48-1 - len (what[i]) - 1 - len (v)) // 8),
                        values[i][v], v))
+print ('#pragma GCC diagnostic pop')
 print ()
 print ("#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)")
 print ()
diff --git a/src/gen-os2-unicode-ranges.py b/src/gen-os2-unicode-ranges.py
new file mode 100644 (file)
index 0000000..8cf5985
--- /dev/null
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+
+# Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
+# Input is a tab seperated list of unicode ranges from the otspec
+# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1).
+
+from __future__ import print_function, division, absolute_import
+
+import io
+import re
+import sys
+
+try:
+  reload(sys)
+  sys.setdefaultencoding('utf-8')
+except NameError:
+  pass  # Python 3
+
+print ("""static OS2Range _hb_os2_unicode_ranges[] =
+{""")
+
+args = sys.argv[1:]
+input_file = args[0]
+
+with io.open(input_file, mode="r", encoding="utf-8") as f:
+
+  all_ranges = [];
+  current_bit = 0
+  while True:
+    line = f.readline().strip()
+    if not line:
+      break
+    fields = re.split(r'\t+', line)
+    if len(fields) == 3:
+      current_bit = fields[0]
+      fields = fields[1:]
+    elif len(fields) > 3:
+      raise Exception("bad input :(.")
+
+    name = fields[0]
+    ranges = re.split("-", fields[1])
+    if len(ranges) != 2:
+      raise Exception("bad input :(.")
+
+    v = tuple((int(ranges[0], 16), int(ranges[1], 16), int(current_bit), name))
+    all_ranges.append(v)
+
+all_ranges = sorted(all_ranges, key=lambda t: t[0])
+
+for ranges in all_ranges:
+  start = ("0x%X" % ranges[0]).rjust(8)
+  end = ("0x%X" % ranges[1]).rjust(8)
+  bit = ("%s" % ranges[2]).rjust(3)
+
+  print ("  {%s, %s, %s}, // %s" % (start, end, bit, ranges[3]))
+
+print ("""};""")
diff --git a/src/gen-tag-table.py b/src/gen-tag-table.py
new file mode 100755 (executable)
index 0000000..1300462
--- /dev/null
@@ -0,0 +1,1126 @@
+#!/usr/bin/python
+
+"""Generator of the mapping from OpenType tags to BCP 47 tags and vice
+versa.
+
+It creates a ``const LangTag[]``, matching the tags from the OpenType
+languages system tag list to the language subtags of the BCP 47 language
+subtag registry, with some manual adjustments. The mappings are
+supplemented with macrolanguages' sublanguages and retired codes'
+replacements, according to BCP 47 and some manual additions where BCP 47
+omits a retired code entirely.
+
+Also generated is a function, ``hb_ot_ambiguous_tag_to_language``,
+intended for use by ``hb_ot_tag_to_language``. It maps OpenType tags
+back to BCP 47 tags. Ambiguous OpenType tags (those that correspond to
+multiple BCP 47 tags) are listed here, except when the alphabetically
+first BCP 47 tag happens to be the chosen disambiguated tag. In that
+case, the fallback behavior will choose the right tag anyway.
+"""
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import collections
+try:
+       from HTMLParser import HTMLParser
+       def write (s):
+               print (s.encode ('utf-8'), end='')
+except ImportError:
+       from html.parser import HTMLParser
+       def write (s):
+               sys.stdout.flush ()
+               sys.stdout.buffer.write (s.encode ('utf-8'))
+import io
+import itertools
+import re
+import sys
+import unicodedata
+
+if len (sys.argv) != 3:
+       print ('usage: ./gen-tag-table.py languagetags language-subtag-registry', file=sys.stderr)
+       sys.exit (1)
+
+try:
+       from html import unescape
+       def html_unescape (parser, entity):
+               return unescape (entity)
+except ImportError:
+       def html_unescape (parser, entity):
+               return parser.unescape (entity)
+
+def expect (condition, message=None):
+       if not condition:
+               if message is None:
+                       raise AssertionError
+               raise AssertionError (message)
+
+# from http://www-01.sil.org/iso639-3/iso-639-3.tab
+ISO_639_3_TO_1 = {
+       'aar': 'aa',
+       'abk': 'ab',
+       'afr': 'af',
+       'aka': 'ak',
+       'amh': 'am',
+       'ara': 'ar',
+       'arg': 'an',
+       'asm': 'as',
+       'ava': 'av',
+       'ave': 'ae',
+       'aym': 'ay',
+       'aze': 'az',
+       'bak': 'ba',
+       'bam': 'bm',
+       'bel': 'be',
+       'ben': 'bn',
+       'bis': 'bi',
+       'bod': 'bo',
+       'bos': 'bs',
+       'bre': 'br',
+       'bul': 'bg',
+       'cat': 'ca',
+       'ces': 'cs',
+       'cha': 'ch',
+       'che': 'ce',
+       'chu': 'cu',
+       'chv': 'cv',
+       'cor': 'kw',
+       'cos': 'co',
+       'cre': 'cr',
+       'cym': 'cy',
+       'dan': 'da',
+       'deu': 'de',
+       'div': 'dv',
+       'dzo': 'dz',
+       'ell': 'el',
+       'eng': 'en',
+       'epo': 'eo',
+       'est': 'et',
+       'eus': 'eu',
+       'ewe': 'ee',
+       'fao': 'fo',
+       'fas': 'fa',
+       'fij': 'fj',
+       'fin': 'fi',
+       'fra': 'fr',
+       'fry': 'fy',
+       'ful': 'ff',
+       'gla': 'gd',
+       'gle': 'ga',
+       'glg': 'gl',
+       'glv': 'gv',
+       'grn': 'gn',
+       'guj': 'gu',
+       'hat': 'ht',
+       'hau': 'ha',
+       'hbs': 'sh',
+       'heb': 'he',
+       'her': 'hz',
+       'hin': 'hi',
+       'hmo': 'ho',
+       'hrv': 'hr',
+       'hun': 'hu',
+       'hye': 'hy',
+       'ibo': 'ig',
+       'ido': 'io',
+       'iii': 'ii',
+       'iku': 'iu',
+       'ile': 'ie',
+       'ina': 'ia',
+       'ind': 'id',
+       'ipk': 'ik',
+       'isl': 'is',
+       'ita': 'it',
+       'jav': 'jv',
+       'jpn': 'ja',
+       'kal': 'kl',
+       'kan': 'kn',
+       'kas': 'ks',
+       'kat': 'ka',
+       'kau': 'kr',
+       'kaz': 'kk',
+       'khm': 'km',
+       'kik': 'ki',
+       'kin': 'rw',
+       'kir': 'ky',
+       'kom': 'kv',
+       'kon': 'kg',
+       'kor': 'ko',
+       'kua': 'kj',
+       'kur': 'ku',
+       'lao': 'lo',
+       'lat': 'la',
+       'lav': 'lv',
+       'lim': 'li',
+       'lin': 'ln',
+       'lit': 'lt',
+       'ltz': 'lb',
+       'lub': 'lu',
+       'lug': 'lg',
+       'mah': 'mh',
+       'mal': 'ml',
+       'mar': 'mr',
+       'mkd': 'mk',
+       'mlg': 'mg',
+       'mlt': 'mt',
+       'mol': 'mo',
+       'mon': 'mn',
+       'mri': 'mi',
+       'msa': 'ms',
+       'mya': 'my',
+       'nau': 'na',
+       'nav': 'nv',
+       'nbl': 'nr',
+       'nde': 'nd',
+       'ndo': 'ng',
+       'nep': 'ne',
+       'nld': 'nl',
+       'nno': 'nn',
+       'nob': 'nb',
+       'nor': 'no',
+       'nya': 'ny',
+       'oci': 'oc',
+       'oji': 'oj',
+       'ori': 'or',
+       'orm': 'om',
+       'oss': 'os',
+       'pan': 'pa',
+       'pli': 'pi',
+       'pol': 'pl',
+       'por': 'pt',
+       'pus': 'ps',
+       'que': 'qu',
+       'roh': 'rm',
+       'ron': 'ro',
+       'run': 'rn',
+       'rus': 'ru',
+       'sag': 'sg',
+       'san': 'sa',
+       'sin': 'si',
+       'slk': 'sk',
+       'slv': 'sl',
+       'sme': 'se',
+       'smo': 'sm',
+       'sna': 'sn',
+       'snd': 'sd',
+       'som': 'so',
+       'sot': 'st',
+       'spa': 'es',
+       'sqi': 'sq',
+       'srd': 'sc',
+       'srp': 'sr',
+       'ssw': 'ss',
+       'sun': 'su',
+       'swa': 'sw',
+       'swe': 'sv',
+       'tah': 'ty',
+       'tam': 'ta',
+       'tat': 'tt',
+       'tel': 'te',
+       'tgk': 'tg',
+       'tgl': 'tl',
+       'tha': 'th',
+       'tir': 'ti',
+       'ton': 'to',
+       'tsn': 'tn',
+       'tso': 'ts',
+       'tuk': 'tk',
+       'tur': 'tr',
+       'twi': 'tw',
+       'uig': 'ug',
+       'ukr': 'uk',
+       'urd': 'ur',
+       'uzb': 'uz',
+       'ven': 've',
+       'vie': 'vi',
+       'vol': 'vo',
+       'wln': 'wa',
+       'wol': 'wo',
+       'xho': 'xh',
+       'yid': 'yi',
+       'yor': 'yo',
+       'zha': 'za',
+       'zho': 'zh',
+       'zul': 'zu',
+}
+
+class LanguageTag (object):
+       """A BCP 47 language tag.
+
+       Attributes:
+               subtags (List[str]): The list of subtags in this tag.
+               grandfathered (bool): Whether this tag is grandfathered. If
+                       ``true``, the entire lowercased tag is the ``language``
+                       and the other subtag fields are empty.
+               language (str): The language subtag.
+               script (str): The script subtag.
+               region (str): The region subtag.
+               variant (str): The variant subtag.
+
+       Args:
+               tag (str): A BCP 47 language tag.
+
+       """
+       def __init__ (self, tag):
+               global bcp_47
+               self.subtags = tag.lower ().split ('-')
+               self.grandfathered = tag.lower () in bcp_47.grandfathered
+               if self.grandfathered:
+                       self.language = tag.lower ()
+                       self.script = ''
+                       self.region = ''
+                       self.variant = ''
+               else:
+                       self.language = self.subtags[0]
+                       self.script = self._find_first (lambda s: len (s) == 4 and s[0] > '9', self.subtags)
+                       self.region = self._find_first (lambda s: len (s) == 2 and s[0] > '9' or len (s) == 3 and s[0] <= '9', self.subtags[1:])
+                       self.variant = self._find_first (lambda s: len (s) > 4 or len (s) == 4 and s[0] <= '9', self.subtags)
+
+       def __str__(self):
+               return '-'.join(self.subtags)
+
+       def __repr__ (self):
+               return 'LanguageTag(%r)' % str(self)
+
+       @staticmethod
+       def _find_first (function, sequence):
+               try:
+                       return next (iter (filter (function, sequence)))
+               except StopIteration:
+                       return None
+
+       def is_complex (self):
+               """Return whether this tag is too complex to represent as a
+               ``LangTag`` in the generated code.
+
+               Complex tags need to be handled in
+               ``hb_ot_tags_from_complex_language``.
+
+               Returns:
+                       Whether this tag is complex.
+               """
+               return not (len (self.subtags) == 1
+                       or self.grandfathered
+                       and len (self.subtags[1]) != 3
+                       and ot.from_bcp_47[self.subtags[0]] == ot.from_bcp_47[self.language])
+
+       def get_group (self):
+               """Return the group into which this tag should be categorized in
+               ``hb_ot_tags_from_complex_language``.
+
+               The group is the first letter of the tag, or ``'und'`` if this tag
+               should not be matched in a ``switch`` statement in the generated
+               code.
+
+               Returns:
+                       This tag's group.
+               """
+               return ('und'
+                       if (self.language == 'und'
+                               or self.variant in bcp_47.prefixes and len (bcp_47.prefixes[self.variant]) == 1)
+                       else self.language[0])
+
+class OpenTypeRegistryParser (HTMLParser):
+       """A parser for the OpenType language system tag registry.
+
+       Attributes:
+               header (str): The "last updated" line of the registry.
+               names (Mapping[str, str]): A map of language system tags to the
+                       names they are given in the registry.
+               ranks (DefaultDict[str, int]): A map of language system tags to
+                       numbers. If a single BCP 47 tag corresponds to multiple
+                       OpenType tags, the tags are ordered in increasing order by
+                       rank. The rank is based on the number of BCP 47 tags
+                       associated with a tag, though it may be manually modified.
+               to_bcp_47 (DefaultDict[str, AbstractSet[str]]): A map of
+                       OpenType language system tags to sets of BCP 47 tags.
+               from_bcp_47 (DefaultDict[str, AbstractSet[str]]): ``to_bcp_47``
+                       inverted. Its values start as unsorted sets;
+                       ``sort_languages`` converts them to sorted lists.
+
+       """
+       def __init__ (self):
+               HTMLParser.__init__ (self)
+               self.header = ''
+               self.names = {}
+               self.ranks = collections.defaultdict (int)
+               self.to_bcp_47 = collections.defaultdict (set)
+               self.from_bcp_47 = collections.defaultdict (set)
+               # Whether the parser is in a <td> element
+               self._td = False
+               # The text of the <td> elements of the current <tr> element.
+               self._current_tr = []
+
+       def handle_starttag (self, tag, attrs):
+               if tag == 'meta':
+                       for attr, value in attrs:
+                               if attr == 'name' and value == 'updated_at':
+                                       self.header = self.get_starttag_text ()
+                                       break
+               elif tag == 'td':
+                       self._td = True
+                       self._current_tr.append ('')
+               elif tag == 'tr':
+                       self._current_tr = []
+
+       def handle_endtag (self, tag):
+               if tag == 'td':
+                       self._td = False
+               elif tag == 'tr' and self._current_tr:
+                       expect (2 <= len (self._current_tr) <= 3)
+                       name = self._current_tr[0].strip ()
+                       tag = self._current_tr[1].strip ("\t\n\v\f\r '")
+                       rank = 0
+                       if len (tag) > 4:
+                               expect (tag.endswith (' (deprecated)'), 'ill-formed OpenType tag: %s' % tag)
+                               name += ' (deprecated)'
+                               tag = tag.split (' ')[0]
+                               rank = 1
+                       self.names[tag] = re.sub (' languages$', '', name)
+                       if not self._current_tr[2]:
+                               return
+                       iso_codes = self._current_tr[2].strip ()
+                       self.to_bcp_47[tag].update (ISO_639_3_TO_1.get (code, code) for code in iso_codes.replace (' ', '').split (','))
+                       rank += 2 * len (self.to_bcp_47[tag])
+                       self.ranks[tag] = rank
+
+       def handle_data (self, data):
+               if self._td:
+                       self._current_tr[-1] += data
+
+       def handle_charref (self, name):
+               self.handle_data (html_unescape (self, '&#%s;' % name))
+
+       def handle_entityref (self, name):
+               self.handle_data (html_unescape (self, '&%s;' % name))
+
+       def parse (self, filename):
+               """Parse the OpenType language system tag registry.
+
+               Args:
+                       filename (str): The file name of the registry.
+               """
+               with io.open (filename, encoding='utf-8') as f:
+                       self.feed (f.read ())
+               expect (self.header)
+               for tag, iso_codes in self.to_bcp_47.items ():
+                       for iso_code in iso_codes:
+                               self.from_bcp_47[iso_code].add (tag)
+
+       def add_language (self, bcp_47_tag, ot_tag):
+               """Add a language as if it were in the registry.
+
+               Args:
+                       bcp_47_tag (str): A BCP 47 tag. If the tag is more than just
+                               a language subtag, and if the language subtag is a
+                               macrolanguage, then new languages are added corresponding
+                               to the macrolanguages' individual languages with the
+                               remainder of the tag appended.
+                       ot_tag (str): An OpenType language system tag.
+               """
+               global bcp_47
+               self.to_bcp_47[ot_tag].add (bcp_47_tag)
+               self.from_bcp_47[bcp_47_tag].add (ot_tag)
+               if bcp_47_tag.lower () not in bcp_47.grandfathered:
+                       try:
+                               [macrolanguage, suffix] = bcp_47_tag.split ('-', 1)
+                               if macrolanguage in bcp_47.macrolanguages:
+                                       s = set ()
+                                       for language in bcp_47.macrolanguages[macrolanguage]:
+                                               if language.lower () not in bcp_47.grandfathered:
+                                                       s.add ('%s-%s' % (language, suffix))
+                                       bcp_47.macrolanguages['%s-%s' % (macrolanguage, suffix)] = s
+                       except ValueError:
+                               pass
+
+       @staticmethod
+       def _remove_language (tag_1, dict_1, dict_2):
+               for tag_2 in dict_1.pop (tag_1):
+                       dict_2[tag_2].remove (tag_1)
+                       if not dict_2[tag_2]:
+                               del dict_2[tag_2]
+
+       def remove_language_ot (self, ot_tag):
+               """Remove an OpenType tag from the registry.
+
+               Args:
+                       ot_tag (str): An OpenType tag.
+               """
+               self._remove_language (ot_tag, self.to_bcp_47, self.from_bcp_47)
+
+       def remove_language_bcp_47 (self, bcp_47_tag):
+               """Remove a BCP 47 tag from the registry.
+
+               Args:
+                       bcp_47_tag (str): A BCP 47 tag.
+               """
+               self._remove_language (bcp_47_tag, self.from_bcp_47, self.to_bcp_47)
+
+       def inherit_from_macrolanguages (self):
+               """Copy mappings from macrolanguages to individual languages.
+
+               If a BCP 47 tag for an individual mapping has no OpenType
+               mapping but its macrolanguage does, the mapping is copied to
+               the individual language. For example, als (Tosk Albanian) has no
+               explicit mapping, so it inherits from sq (Albanian) the mapping
+               to SQI.
+
+               If a BCP 47 tag for a macrolanguage has no OpenType mapping but
+               all of its individual languages do and they all map to the same
+               tags, the mapping is copied to the macrolanguage.
+               """
+               global bcp_47
+               original_ot_from_bcp_47 = dict (self.from_bcp_47)
+               for macrolanguage, languages in dict (bcp_47.macrolanguages).items ():
+                       ot_macrolanguages = set (original_ot_from_bcp_47.get (macrolanguage, set ()))
+                       if ot_macrolanguages:
+                               for ot_macrolanguage in ot_macrolanguages:
+                                       for language in languages:
+                                               # Remove the following condition if e.g. nn should map to NYN,NOR
+                                               # instead of just NYN.
+                                               if language not in original_ot_from_bcp_47:
+                                                       self.add_language (language, ot_macrolanguage)
+                                                       self.ranks[ot_macrolanguage] += 1
+                       else:
+                               for language in languages:
+                                       if language in original_ot_from_bcp_47:
+                                               if ot_macrolanguages:
+                                                       ml = original_ot_from_bcp_47[language]
+                                                       if ml:
+                                                               ot_macrolanguages &= ml
+                                                       else:
+                                                               pass
+                                               else:
+                                                       ot_macrolanguages |= original_ot_from_bcp_47[language]
+                                       else:
+                                               ot_macrolanguages.clear ()
+                                       if not ot_macrolanguages:
+                                               break
+                               for ot_macrolanguage in ot_macrolanguages:
+                                       self.add_language (macrolanguage, ot_macrolanguage)
+
+       def sort_languages (self):
+               """Sort the values of ``from_bcp_47`` in ascending rank order."""
+               for language, tags in self.from_bcp_47.items ():
+                       self.from_bcp_47[language] = sorted (tags,
+                                       key=lambda t: (self.ranks[t] + rank_delta (language, t), t))
+
+ot = OpenTypeRegistryParser ()
+
+class BCP47Parser (object):
+       """A parser for the BCP 47 subtag registry.
+
+       Attributes:
+               header (str): The "File-Date" line of the registry.
+               names (Mapping[str, str]): A map of subtags to the names they
+                       are given in the registry. Each value is a
+                       ``'\\n'``-separated list of names.
+               scopes (Mapping[str, str]): A map of language subtags to strings
+                       suffixed to language names, including suffixes to explain
+                       language scopes.
+               macrolanguages (DefaultDict[str, AbstractSet[str]]): A map of
+                       language subtags to the sets of language subtags which
+                       inherit from them. See
+                       ``OpenTypeRegistryParser.inherit_from_macrolanguages``.
+               prefixes (DefaultDict[str, AbstractSet[str]]): A map of variant
+                       subtags to their prefixes.
+               grandfathered (AbstractSet[str]): The set of grandfathered tags,
+                       normalized to lowercase.
+
+       """
+       def __init__ (self):
+               self.header = ''
+               self.names = {}
+               self.scopes = {}
+               self.macrolanguages = collections.defaultdict (set)
+               self.prefixes = collections.defaultdict (set)
+               self.grandfathered = set ()
+
+       def parse (self, filename):
+               """Parse the BCP 47 subtag registry.
+
+               Args:
+                       filename (str): The file name of the registry.
+               """
+               with io.open (filename, encoding='utf-8') as f:
+                       subtag_type = None
+                       subtag = None
+                       deprecated = False
+                       has_preferred_value = False
+                       line_buffer = ''
+                       for line in itertools.chain (f, ['']):
+                               line = line.rstrip ()
+                               if line.startswith (' '):
+                                       line_buffer += line[1:]
+                                       continue
+                               line, line_buffer = line_buffer, line
+                               if line.startswith ('Type: '):
+                                       subtag_type = line.split (' ')[1]
+                                       deprecated = False
+                                       has_preferred_value = False
+                               elif line.startswith ('Subtag: ') or line.startswith ('Tag: '):
+                                       subtag = line.split (' ')[1]
+                                       if subtag_type == 'grandfathered':
+                                               self.grandfathered.add (subtag.lower ())
+                               elif line.startswith ('Description: '):
+                                       description = line.split (' ', 1)[1].replace (' (individual language)', '')
+                                       description = re.sub (' (\((individual |macro)language\)|languages)$', '',
+                                                       description)
+                                       if subtag in self.names:
+                                               self.names[subtag] += '\n' + description
+                                       else:
+                                               self.names[subtag] = description
+                               elif subtag_type == 'language' or subtag_type == 'grandfathered':
+                                       if line.startswith ('Scope: '):
+                                               scope = line.split (' ')[1]
+                                               if scope == 'macrolanguage':
+                                                       scope = ' [macrolanguage]'
+                                               elif scope == 'collection':
+                                                       scope = ' [family]'
+                                               else:
+                                                       continue
+                                               self.scopes[subtag] = scope
+                                       elif line.startswith ('Deprecated: '):
+                                               self.scopes[subtag] = ' (retired code)' + self.scopes.get (subtag, '')
+                                               deprecated = True
+                                       elif deprecated and line.startswith ('Comments: see '):
+                                               # If a subtag is split into multiple replacement subtags,
+                                               # it essentially represents a macrolanguage.
+                                               for language in line.replace (',', '').split (' ')[2:]:
+                                                       self._add_macrolanguage (subtag, language)
+                                       elif line.startswith ('Preferred-Value: '):
+                                               # If a subtag is deprecated in favor of a single replacement subtag,
+                                               # it is either a dialect or synonym of the preferred subtag. Either
+                                               # way, it is close enough to the truth to consider the replacement
+                                               # the macrolanguage of the deprecated language.
+                                               has_preferred_value = True
+                                               macrolanguage = line.split (' ')[1]
+                                               self._add_macrolanguage (macrolanguage, subtag)
+                                       elif not has_preferred_value and line.startswith ('Macrolanguage: '):
+                                               self._add_macrolanguage (line.split (' ')[1], subtag)
+                               elif subtag_type == 'variant':
+                                       if line.startswith ('Prefix: '):
+                                               self.prefixes[subtag].add (line.split (' ')[1])
+                               elif line.startswith ('File-Date: '):
+                                       self.header = line
+               expect (self.header)
+
+       def _add_macrolanguage (self, macrolanguage, language):
+               global ot
+               if language not in ot.from_bcp_47:
+                       for l in self.macrolanguages.get (language, set ()):
+                               self._add_macrolanguage (macrolanguage, l)
+               if macrolanguage not in ot.from_bcp_47:
+                       for ls in list (self.macrolanguages.values ()):
+                               if macrolanguage in ls:
+                                       ls.add (language)
+                                       return
+               self.macrolanguages[macrolanguage].add (language)
+
+       def remove_extra_macrolanguages (self):
+               """Make every language have at most one macrolanguage."""
+               inverted = collections.defaultdict (list)
+               for macrolanguage, languages in self.macrolanguages.items ():
+                       for language in languages:
+                               inverted[language].append (macrolanguage)
+               for language, macrolanguages in inverted.items ():
+                       if len (macrolanguages) > 1:
+                               macrolanguages.sort (key=lambda ml: len (self.macrolanguages[ml]))
+                               biggest_macrolanguage = macrolanguages.pop ()
+                               for macrolanguage in macrolanguages:
+                                       self._add_macrolanguage (biggest_macrolanguage, macrolanguage)
+
+       def get_name (self, lt):
+               """Return the names of the subtags in a language tag.
+
+               Args:
+                       lt (LanguageTag): A BCP 47 language tag.
+
+               Returns:
+                       The name form of ``lt``.
+               """
+               name = self.names[lt.language].split ('\n')[0]
+               if lt.script:
+                       name += '; ' + self.names[lt.script.title ()].split ('\n')[0]
+               if lt.region:
+                       name += '; ' + self.names[lt.region.upper ()].split ('\n')[0]
+               if lt.variant:
+                       name += '; ' + self.names[lt.variant].split ('\n')[0]
+               return name
+
+bcp_47 = BCP47Parser ()
+
+ot.parse (sys.argv[1])
+bcp_47.parse (sys.argv[2])
+
+ot.add_language ('ary', 'MOR')
+
+ot.add_language ('ath', 'ATH')
+
+ot.add_language ('bai', 'BML')
+
+ot.ranks['BAL'] = ot.ranks['KAR'] + 1
+
+ot.add_language ('ber', 'BBR')
+
+ot.remove_language_ot ('PGR')
+ot.add_language ('el-polyton', 'PGR')
+
+bcp_47.macrolanguages['et'] = {'ekk'}
+
+bcp_47.names['flm'] = 'Falam Chin'
+bcp_47.scopes['flm'] = ' (retired code)'
+bcp_47.macrolanguages['flm'] = {'cfm'}
+
+ot.ranks['FNE'] = ot.ranks['TNE'] + 1
+
+ot.add_language ('und-fonipa', 'IPPH')
+
+ot.add_language ('und-fonnapa', 'APPH')
+
+ot.remove_language_ot ('IRT')
+ot.add_language ('ga-Latg', 'IRT')
+
+ot.remove_language_ot ('KGE')
+ot.add_language ('und-Geok', 'KGE')
+
+ot.add_language ('guk', 'GUK')
+ot.names['GUK'] = 'Gumuz (SIL fonts)'
+ot.ranks['GUK'] = ot.ranks['GMZ'] + 1
+
+bcp_47.macrolanguages['id'] = {'in'}
+
+bcp_47.macrolanguages['ijo'] = {'ijc'}
+
+ot.add_language ('kht', 'KHN')
+ot.names['KHN'] = ot.names['KHT'] + ' (Microsoft fonts)'
+ot.names['KHT'] = ot.names['KHT'] + ' (OpenType spec and SIL fonts)'
+ot.ranks['KHN'] = ot.ranks['KHT']
+ot.ranks['KHT'] += 1
+
+ot.ranks['LCR'] = ot.ranks['MCR'] + 1
+
+ot.names['MAL'] = 'Malayalam Traditional'
+ot.ranks['MLR'] += 1
+
+bcp_47.names['mhv'] = 'Arakanese'
+bcp_47.scopes['mhv'] = ' (retired code)'
+
+ot.add_language ('no', 'NOR')
+
+ot.add_language ('oc-provenc', 'PRO')
+
+ot.add_language ('qu', 'QUZ')
+ot.add_language ('qub', 'QWH')
+ot.add_language ('qud', 'QVI')
+ot.add_language ('qug', 'QVI')
+ot.add_language ('qup', 'QVI')
+ot.add_language ('qur', 'QWH')
+ot.add_language ('qus', 'QUH')
+ot.add_language ('quw', 'QVI')
+ot.add_language ('qux', 'QWH')
+ot.add_language ('qva', 'QWH')
+ot.add_language ('qvh', 'QWH')
+ot.add_language ('qvj', 'QVI')
+ot.add_language ('qvl', 'QWH')
+ot.add_language ('qvm', 'QWH')
+ot.add_language ('qvn', 'QWH')
+ot.add_language ('qvo', 'QVI')
+ot.add_language ('qvp', 'QWH')
+ot.add_language ('qvw', 'QWH')
+ot.add_language ('qvz', 'QVI')
+ot.add_language ('qwa', 'QWH')
+ot.add_language ('qws', 'QWH')
+ot.add_language ('qxa', 'QWH')
+ot.add_language ('qxc', 'QWH')
+ot.add_language ('qxh', 'QWH')
+ot.add_language ('qxl', 'QVI')
+ot.add_language ('qxn', 'QWH')
+ot.add_language ('qxo', 'QWH')
+ot.add_language ('qxr', 'QVI')
+ot.add_language ('qxt', 'QWH')
+ot.add_language ('qxw', 'QWH')
+
+bcp_47.macrolanguages['ro'].remove ('mo')
+bcp_47.macrolanguages['ro-MD'].add ('mo')
+
+ot.add_language ('sgw', 'SGW')
+ot.names['SGW'] = ot.names['CHG'] + ' (SIL fonts)'
+ot.ranks['SGW'] = ot.ranks['CHG'] + 1
+
+ot.remove_language_ot ('SYRE')
+ot.remove_language_ot ('SYRJ')
+ot.remove_language_ot ('SYRN')
+ot.add_language ('und-Syre', 'SYRE')
+ot.add_language ('und-Syrj', 'SYRJ')
+ot.add_language ('und-Syrn', 'SYRN')
+
+bcp_47.names['xst'] = u"Silt'e"
+bcp_47.scopes['xst'] = ' (retired code)'
+bcp_47.macrolanguages['xst'] = {'stv', 'wle'}
+
+ot.add_language ('xwo', 'TOD')
+
+ot.remove_language_ot ('ZHH')
+ot.remove_language_ot ('ZHP')
+ot.remove_language_ot ('ZHT')
+bcp_47.macrolanguages['zh'].remove ('lzh')
+bcp_47.macrolanguages['zh'].remove ('yue')
+ot.add_language ('zh-Hant-MO', 'ZHH')
+ot.add_language ('zh-Hant-HK', 'ZHH')
+ot.add_language ('zh-Hans', 'ZHS')
+ot.add_language ('zh-Hant', 'ZHT')
+ot.add_language ('zh-HK', 'ZHH')
+ot.add_language ('zh-MO', 'ZHH')
+ot.add_language ('zh-TW', 'ZHT')
+ot.add_language ('lzh', 'ZHT')
+ot.add_language ('lzh-Hans', 'ZHS')
+ot.add_language ('yue', 'ZHH')
+ot.add_language ('yue-Hans', 'ZHS')
+
+bcp_47.macrolanguages['zom'] = {'yos'}
+
+def rank_delta (bcp_47, ot):
+       """Return a delta to apply to a BCP 47 tag's rank.
+
+       Most OpenType tags have a constant rank, but a few have ranks that
+       depend on the BCP 47 tag.
+
+       Args:
+               bcp_47 (str): A BCP 47 tag.
+               ot (str): An OpenType tag to.
+
+       Returns:
+               A number to add to ``ot``'s rank when sorting ``bcp_47``'s
+               OpenType equivalents.
+       """
+       if bcp_47 == 'ak' and ot == 'AKA':
+               return -1
+       if bcp_47 == 'tw' and ot == 'TWI':
+               return -1
+       return 0
+
+disambiguation = {
+       'ALT': 'alt',
+       'ARK': 'rki',
+       'BHI': 'bhb',
+       'BLN': 'bjt',
+       'BTI': 'beb',
+       'CCHN': 'cco',
+       'CMR': 'swb',
+       'CPP': 'crp',
+       'CRR': 'crx',
+       'DUJ': 'dwu',
+       'ECR': 'crj',
+       'HAL': 'cfm',
+       'HND': 'hnd',
+       'KIS': 'kqs',
+       'LRC': 'bqi',
+       'NDB': 'nd',
+       'NIS': 'njz',
+       'PLG': 'pce',
+       'PRO': 'pro',
+       'QIN': 'bgr',
+       'QUH': 'quh',
+       'QVI': 'qvi',
+       'QWH': 'qwh',
+       'SIG': 'stv',
+       'TNE': 'yrk',
+       'ZHH': 'zh-HK',
+       'ZHS': 'zh-Hans',
+       'ZHT': 'zh-Hant',
+}
+
+ot.inherit_from_macrolanguages ()
+bcp_47.remove_extra_macrolanguages ()
+ot.inherit_from_macrolanguages ()
+ot.sort_languages ()
+
+print ('/* == Start of generated table == */')
+print ('/*')
+print (' * The following table is generated by running:')
+print (' *')
+print (' *   %s languagetags language-subtag-registry' % sys.argv[0])
+print (' *')
+print (' * on files with these headers:')
+print (' *')
+print (' * %s' % ot.header.strip ())
+print (' * %s' % bcp_47.header)
+print (' */')
+print ()
+print ('#ifndef HB_OT_TAG_TABLE_HH')
+print ('#define HB_OT_TAG_TABLE_HH')
+print ()
+print ('static const LangTag ot_languages[] = {')
+
+def hb_tag (tag):
+       """Convert a tag to ``HB_TAG`` form.
+
+       Args:
+               tag (str): An OpenType tag.
+
+       Returns:
+               A snippet of C++ representing ``tag``.
+       """
+       return u"HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
+
+def get_variant_set (name):
+       """Return a set of variant language names from a name.
+
+       Args:
+               name (str): A list of language names from the BCP 47 registry,
+                       joined on ``'\\n'``.
+
+       Returns:
+               A set of normalized language names.
+       """
+       return set (unicodedata.normalize ('NFD', n.replace ('\u2019', u"'"))
+                       .encode ('ASCII', 'ignore')
+                       .strip ()
+                       for n in re.split ('[\n(),]', name) if n)
+
+def language_name_intersection (a, b):
+       """Return the names in common between two language names.
+
+       Args:
+               a (str): A list of language names from the BCP 47 registry,
+                       joined on ``'\\n'``.
+               b (str): A list of language names from the BCP 47 registry,
+                       joined on ``'\\n'``.
+
+       Returns:
+               The normalized language names shared by ``a`` and ``b``.
+       """
+       return get_variant_set (a).intersection (get_variant_set (b))
+
+def get_matching_language_name (intersection, candidates):
+       return next (iter (c for c in candidates if not intersection.isdisjoint (get_variant_set (c))))
+
+maximum_tags = 0
+for language, tags in sorted (ot.from_bcp_47.items ()):
+       if language == '' or '-' in language:
+               continue
+       print ('  {\"%s\",\t{' % language, end='')
+       maximum_tags = max (maximum_tags, len (tags))
+       tag_count = len (tags)
+       for i, tag in enumerate (tags, start=1):
+               if i > 1:
+                       print ('\t\t ', end='')
+               print (hb_tag (tag), end='')
+               if i == tag_count:
+                       print ('}}', end='')
+               print (',\t/* ', end='')
+               bcp_47_name = bcp_47.names.get (language, '')
+               bcp_47_name_candidates = bcp_47_name.split ('\n')
+               intersection = language_name_intersection (bcp_47_name, ot.names[tag])
+               scope = bcp_47.scopes.get (language, '')
+               if not intersection:
+                       write ('%s%s -> %s' % (bcp_47_name_candidates[0], scope, ot.names[tag]))
+               else:
+                       name = get_matching_language_name (intersection, bcp_47_name_candidates)
+                       bcp_47.names[language] = name
+                       write ('%s%s' % (name if len (name) > len (ot.names[tag]) else ot.names[tag], scope))
+               print (' */')
+
+print ('};')
+print ()
+print ('static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == %iu, "");' % maximum_tags)
+print ()
+
+print ('/**')
+print (' * hb_ot_tags_from_complex_language:')
+print (' * @lang_str: a BCP 47 language tag to convert.')
+print (' * @limit: a pointer to the end of the substring of @lang_str to consider for')
+print (' * conversion.')
+print (' * @count: maximum number of language tags to retrieve (IN) and actual number of')
+print (' * language tags retrieved (OUT). If no tags are retrieved, it is not modified.')
+print (' * @tags: array of size at least @language_count to store the language tag')
+print (' * results')
+print (' *')
+print (' * Converts a multi-subtag BCP 47 language tag to language tags.')
+print (' *')
+print (' * Return value: Whether any language systems were retrieved.')
+print (' **/')
+print ('static bool')
+print ('hb_ot_tags_from_complex_language (const char   *lang_str,')
+print ('\t\t\t\t  const char   *limit,')
+print ('\t\t\t\t  unsigned int *count /* IN/OUT */,')
+print ('\t\t\t\t  hb_tag_t     *tags /* OUT */)')
+print ('{')
+
+def print_subtag_matches (subtag, new_line):
+       if subtag:
+               if new_line:
+                       print ()
+                       print ('\t&& ', end='')
+               print ('subtag_matches (lang_str, limit, "-%s")' % subtag, end='')
+
+complex_tags = collections.defaultdict (list)
+for initial, group in itertools.groupby ((lt_tags for lt_tags in [
+                       (LanguageTag (language), tags)
+                       for language, tags in sorted (ot.from_bcp_47.items (),
+                               key=lambda i: (-len (i[0]), i[0]))
+               ] if lt_tags[0].is_complex ()),
+               key=lambda lt_tags: lt_tags[0].get_group ()):
+       complex_tags[initial] += group
+
+for initial, items in sorted (complex_tags.items ()):
+       if initial != 'und':
+               continue
+       for lt, tags in items:
+               if lt.variant in bcp_47.prefixes:
+                       expect (next (iter (bcp_47.prefixes[lt.variant])) == lt.language,
+                                       '%s is not a valid prefix of %s' % (lt.language, lt.variant))
+               print ('  if (', end='')
+               print_subtag_matches (lt.script, False)
+               print_subtag_matches (lt.region, False)
+               print_subtag_matches (lt.variant, False)
+               print (')')
+               print ('  {')
+               write ('    /* %s */' % bcp_47.get_name (lt))
+               print ()
+               if len (tags) == 1:
+                       write ('    tags[0] = %s;  /* %s */' % (hb_tag (tags[0]), ot.names[tags[0]]))
+                       print ()
+                       print ('    *count = 1;')
+               else:
+                       print ('    hb_tag_t possible_tags[] = {')
+                       for tag in tags:
+                               write ('      %s,  /* %s */' % (hb_tag (tag), ot.names[tag]))
+                               print ()
+                       print ('    };')
+                       print ('    for (i = 0; i < %s && i < *count; i++)' % len (tags))
+                       print ('      tags[i] = possible_tags[i];')
+                       print ('    *count = i;')
+               print ('    return true;')
+               print ('  }')
+
+print ('  switch (lang_str[0])')
+print ('  {')
+for initial, items in sorted (complex_tags.items ()):
+       if initial == 'und':
+               continue
+       print ("  case '%s':" % initial)
+       for lt, tags in items:
+               print ('    if (', end='')
+               if lt.grandfathered:
+                       print ('0 == strcmp (&lang_str[1], "%s")' % lt.language[1:], end='')
+               else:
+                       string_literal = lt.language[1:] + '-'
+                       if lt.script:
+                               string_literal += lt.script
+                               lt.script = None
+                               if lt.region:
+                                       string_literal += '-' + lt.region
+                                       lt.region = None
+                       if string_literal[-1] == '-':
+                               print ('0 == strncmp (&lang_str[1], "%s", %i)' % (string_literal, len (string_literal)), end='')
+                       else:
+                               print ('lang_matches (&lang_str[1], "%s")' % string_literal, end='')
+               print_subtag_matches (lt.script, True)
+               print_subtag_matches (lt.region, True)
+               print_subtag_matches (lt.variant, True)
+               print (')')
+               print ('    {')
+               write ('      /* %s */' % bcp_47.get_name (lt))
+               print ()
+               if len (tags) == 1:
+                       write ('      tags[0] = %s;  /* %s */' % (hb_tag (tags[0]), ot.names[tags[0]]))
+                       print ()
+                       print ('      *count = 1;')
+               else:
+                       print ('      unsigned int i;')
+                       print ('      hb_tag_t possible_tags[] = {')
+                       for tag in tags:
+                               write ('\t%s,  /* %s */' % (hb_tag (tag), ot.names[tag]))
+                               print ()
+                       print ('      };')
+                       print ('      for (i = 0; i < %s && i < *count; i++)' % len (tags))
+                       print ('\ttags[i] = possible_tags[i];')
+                       print ('      *count = i;')
+               print ('      return true;')
+               print ('    }')
+       print ('    break;')
+
+print ('  }')
+print ('  return false;')
+print ('}')
+print ()
+print ('/**')
+print (' * hb_ot_ambiguous_tag_to_language')
+print (' * @tag: A language tag.')
+print (' *')
+print (' * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to')
+print (' * many language tags) and the best tag is not the alphabetically first, or if')
+print (' * the best tag consists of multiple subtags.')
+print (' *')
+print (' * Return value: The #hb_language_t corresponding to the BCP 47 language tag,')
+print (' * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.')
+print (' **/')
+print ('static hb_language_t')
+print ('hb_ot_ambiguous_tag_to_language (hb_tag_t tag)')
+print ('{')
+print ('  switch (tag)')
+print ('  {')
+
+def verify_disambiguation_dict ():
+       """Verify and normalize ``disambiguation``.
+
+       ``disambiguation`` is a map of ambiguous OpenType language system
+       tags to the particular BCP 47 tags they correspond to. This function
+       checks that all its keys really are ambiguous and that each key's
+       value is valid for that key. It checks that no ambiguous tag is
+       missing, except when it can figure out which BCP 47 tag is the best
+       by itself.
+
+       It modifies ``disambiguation`` to remove keys whose values are the
+       same as those that the fallback would return anyway, and to add
+       ambiguous keys whose disambiguations it determined automatically.
+
+       Raises:
+               AssertionError: Verification failed.
+       """
+       global bcp_47
+       global disambiguation
+       global ot
+       for ot_tag, bcp_47_tags in ot.to_bcp_47.items ():
+               primary_tags = list (t for t in bcp_47_tags if t not in bcp_47.grandfathered and ot.from_bcp_47.get (t)[0] == ot_tag)
+               if len (primary_tags) == 1:
+                       expect (ot_tag not in disambiguation, 'unnecessary disambiguation for OT tag: %s' % ot_tag)
+                       if '-' in primary_tags[0]:
+                               disambiguation[ot_tag] = primary_tags[0]
+               elif len (primary_tags) == 0:
+                       expect (ot_tag not in disambiguation, 'There is no possible valid disambiguation for %s' % ot_tag)
+               else:
+                       macrolanguages = list (t for t in primary_tags if bcp_47.scopes.get (t) == ' [macrolanguage]')
+                       if len (macrolanguages) != 1:
+                               macrolanguages = list (t for t in primary_tags if bcp_47.scopes.get (t) == ' [family]')
+                       if len (macrolanguages) != 1:
+                               macrolanguages = list (t for t in primary_tags if 'retired code' not in bcp_47.scopes.get (t, ''))
+                       if len (macrolanguages) != 1:
+                               expect (ot_tag in disambiguation, 'ambiguous OT tag: %s %s' % (ot_tag, str (macrolanguages)))
+                               expect (disambiguation[ot_tag] in bcp_47_tags,
+                                               '%s is not a valid disambiguation for %s' % (disambiguation[ot_tag], ot_tag))
+                       elif ot_tag not in disambiguation:
+                               disambiguation[ot_tag] = macrolanguages[0]
+                       if disambiguation[ot_tag] == sorted (primary_tags)[0] and '-' not in disambiguation[ot_tag]:
+                               del disambiguation[ot_tag]
+       for ot_tag in disambiguation.keys ():
+               expect (ot_tag in ot.to_bcp_47, 'unknown OT tag: %s' % ot_tag)
+
+verify_disambiguation_dict ()
+for ot_tag, bcp_47_tag in sorted (disambiguation.items ()):
+       write ('  case %s:  /* %s */' % (hb_tag (ot_tag), ot.names[ot_tag]))
+       print ()
+       write ('    return hb_language_from_string (\"%s\", -1);  /* %s */' % (bcp_47_tag, bcp_47.get_name (LanguageTag (bcp_47_tag))))
+       print ()
+
+print ('  default:')
+print ('    return HB_LANGUAGE_INVALID;')
+print ('  }')
+print ('}')
+
+print ()
+print ('#endif /* HB_OT_TAG_TABLE_HH */')
+print ()
+print ('/* == End of generated table == */')
+
index 6aa5f88..be204b6 100755 (executable)
@@ -1,14 +1,16 @@
 #!/usr/bin/env python
+# flake8: noqa
 
 from __future__ import print_function, division, absolute_import
 
-import io, sys
+import io
+import sys
 
 if len (sys.argv) != 5:
        print ("usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
        sys.exit (1)
 
-BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"]
+BLACKLISTED_BLOCKS = ["Thai", "Lao"]
 
 files = [io.open (x, encoding='utf-8') for x in sys.argv[1:]]
 
@@ -47,6 +49,11 @@ defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
 data[0][0x034F] = defaults[0]
 data[0][0x2060] = defaults[0]
 data[0][0x20F0] = defaults[0]
+# TODO https://github.com/roozbehp/unicode-data/issues/9
+data[0][0x11C44] = 'Consonant_Placeholder'
+data[0][0x11C45] = 'Consonant_Placeholder'
+# TODO https://github.com/harfbuzz/harfbuzz/pull/1399
+data[0][0x111C8] = 'Consonant_Placeholder'
 for u in range (0xFE00, 0xFE0F + 1):
        data[0][u] = defaults[0]
 
@@ -165,7 +172,7 @@ def is_BASE(U, UISC, UGC):
 def is_BASE_IND(U, UISC, UGC):
        #SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
        return (UISC in [Consonant_Dead, Modifying_Letter] or
-               (UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x11A3F, 0x11A45]) or
+               (UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
                False # SPEC-DRAFT-OUTDATED! U == 0x002D
                )
 def is_BASE_NUM(U, UISC, UGC):
@@ -194,7 +201,11 @@ def is_CONS_SUB(U, UISC, UGC):
 def is_CONS_WITH_STACKER(U, UISC, UGC):
        return UISC == Consonant_With_Stacker
 def is_HALANT(U, UISC, UGC):
-       return UISC in [Virama, Invisible_Stacker]
+       return UISC in [Virama, Invisible_Stacker] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
+def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC):
+       # https://github.com/harfbuzz/harfbuzz/issues/1102
+       # https://github.com/harfbuzz/harfbuzz/issues/1379
+       return U in [0x11046, 0x1134D]
 def is_HALANT_NUM(U, UISC, UGC):
        return UISC == Number_Joiner
 def is_ZWNJ(U, UISC, UGC):
@@ -245,6 +256,7 @@ use_mapping = {
        'SUB':  is_CONS_SUB,
        'CS':   is_CONS_WITH_STACKER,
        'H':    is_HALANT,
+       'HVM':  is_HALANT_OR_VOWEL_MODIFIER,
        'HN':   is_HALANT_NUM,
        'ZWNJ': is_ZWNJ,
        'ZWJ':  is_ZWJ,
@@ -278,8 +290,8 @@ use_positions = {
        'V': {
                'Abv': [Top, Top_And_Bottom, Top_And_Bottom_And_Right, Top_And_Right],
                'Blw': [Bottom, Overstruck, Bottom_And_Right],
-               'Pst': [Right],
-               'Pre': [Left, Top_And_Left, Top_And_Left_And_Right, Left_And_Right],
+               'Pst': [Right, Top_And_Left, Top_And_Left_And_Right, Left_And_Right],
+               'Pre': [Left],
        },
        'VM': {
                'Abv': [Top],
@@ -292,6 +304,7 @@ use_positions = {
                'Blw': [Bottom],
        },
        'H': None,
+       'HVM': None,
        'B': None,
        'FM': None,
        'SUB': None,
@@ -304,11 +317,28 @@ def map_to_use(data):
 
                # Resolve Indic_Syllabic_Category
 
-               # TODO: These don't have UISC assigned in Unicode 8.0, but
-               # have UIPC
+               # TODO: These don't have UISC assigned in Unicode 8.0, but have UIPC
                if U == 0x17DD: UISC = Vowel_Dependent
                if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
 
+               # Tibetan:
+               # TODO: These don't have UISC assigned in Unicode 11.0, but have UIPC
+               if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
+               if 0x0F86 <= U <= 0x0F87: UISC = Tone_Mark
+               # Overrides to allow NFC order matching syllable
+               # https://github.com/harfbuzz/harfbuzz/issues/1012
+               if UBlock == 'Tibetan' and is_VOWEL (U, UISC, UGC):
+                       if UIPC == Top:
+                               UIPC = Bottom
+
+               # TODO: https://github.com/harfbuzz/harfbuzz/pull/982
+               # also  https://github.com/harfbuzz/harfbuzz/issues/1012
+               if UBlock == 'Chakma' and is_VOWEL (U, UISC, UGC):
+                       if UIPC == Top:
+                               UIPC = Bottom
+                       elif UIPC == Bottom:
+                               UIPC = Top
+
                # TODO: https://github.com/harfbuzz/harfbuzz/pull/627
                if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
 
@@ -325,6 +355,12 @@ def map_to_use(data):
                # TODO: https://github.com/harfbuzz/harfbuzz/pull/626
                if U == 0xA8B4: UISC = Consonant_Medial
 
+               # TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
+               if U == 0x11134: UISC = Gemination_Mark
+
+               # TODO: https://github.com/harfbuzz/harfbuzz/pull/1399
+               if U == 0x111C9: UISC = Consonant_Final
+
                values = [k for k,v in items if v(U,UISC,UGC)]
                assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
                USE = values[0]
@@ -344,6 +380,9 @@ def map_to_use(data):
                if 0xA926 <= U <= 0xA92A: UIPC = Top
                if U == 0x111CA: UIPC = Bottom
                if U == 0x11300: UIPC = Top
+               # TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
+               if U == 0x11302: UIPC = Top
+               if U == 0x1133C: UIPC = Bottom
                if U == 0x1171E: UIPC = Left # Correct?!
                if 0x1CF2 <= U <= 0x1CF3: UIPC = Right
                if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
@@ -378,7 +417,7 @@ for h in headers:
                print (" * %s" % (l.strip()))
 print (" */")
 print ()
-print ('#include "hb-ot-shape-complex-use-private.hh"')
+print ('#include "hb-ot-shape-complex-use.hh"')
 print ()
 
 total = 0
@@ -416,6 +455,8 @@ num = 0
 offset = 0
 starts = []
 ends = []
+print ('#pragma GCC diagnostic push')
+print ('#pragma GCC diagnostic ignored "-Wunused-macros"')
 for k,v in sorted(use_mapping.items()):
        if k in use_positions and use_positions[k]: continue
        print ("#define %s      USE_%s  /* %s */" % (k, k, v.__name__[3:]))
@@ -424,6 +465,7 @@ for k,v in sorted(use_positions.items()):
        for suf in v.keys():
                tag = k + suf
                print ("#define %s      USE_%s" % (tag, tag))
+print ('#pragma GCC diagnostic pop')
 print ("")
 print ("static const USE_TABLE_ELEMENT_TYPE use_table[] = {")
 for u in uu:
diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py
new file mode 100755 (executable)
index 0000000..b7f6be2
--- /dev/null
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+
+"""Generator of the function to prohibit certain vowel sequences.
+
+It creates ``_hb_preprocess_text_vowel_constraints``, which inserts dotted
+circles into sequences prohibited by the USE script development spec.
+This function should be used as the ``preprocess_text`` of an
+``hb_ot_complex_shaper_t``.
+"""
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import collections
+try:
+       from HTMLParser import HTMLParser
+       def write (s):
+               print (s.encode ('utf-8'), end='')
+except ImportError:
+       from html.parser import HTMLParser
+       def write (s):
+               sys.stdout.flush ()
+               sys.stdout.buffer.write (s.encode ('utf-8'))
+import itertools
+import io
+import sys
+
+if len (sys.argv) != 3:
+       print ('usage: ./gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt', file=sys.stderr)
+       sys.exit (1)
+
+with io.open (sys.argv[2], encoding='utf-8') as f:
+       scripts_header = [f.readline () for i in range (2)]
+       scripts = {}
+       script_order = {}
+       for line in f:
+               j = line.find ('#')
+               if j >= 0:
+                       line = line[:j]
+               fields = [x.strip () for x in line.split (';')]
+               if len (fields) == 1:
+                       continue
+               uu = fields[0].split ('..')
+               start = int (uu[0], 16)
+               if len (uu) == 1:
+                       end = start
+               else:
+                       end = int (uu[1], 16)
+               script = fields[1]
+               for u in range (start, end + 1):
+                       scripts[u] = script
+               if script not in script_order:
+                       script_order[script] = start
+
+class ConstraintSet (object):
+       """A set of prohibited code point sequences.
+
+       Args:
+               constraint (List[int]): A prohibited code point sequence.
+
+       """
+       def __init__ (self, constraint):
+               # Either a list or a dictionary. As a list of code points, it
+               # represents a prohibited code point sequence. As a dictionary,
+               # it represents a set of prohibited sequences, where each item
+               # represents the set of prohibited sequences starting with the
+               # key (a code point) concatenated with any of the values
+               # (ConstraintSets).
+               self._c = constraint
+
+       def add (self, constraint):
+               """Add a constraint to this set."""
+               if not constraint:
+                       return
+               first = constraint[0]
+               rest = constraint[1:]
+               if isinstance (self._c, list):
+                       if constraint == self._c[:len (constraint)]:
+                               self._c = constraint
+                       elif self._c != constraint[:len (self._c)]:
+                               self._c = {self._c[0]: ConstraintSet (self._c[1:])}
+               if isinstance (self._c, dict):
+                       if first in self._c:
+                               self._c[first].add (rest)
+                       else:
+                               self._c[first] = ConstraintSet (rest)
+
+       def _indent (self, depth):
+               return ('  ' * depth).replace ('        ', '\t')
+
+       def __str__ (self, index=0, depth=4):
+               s = []
+               indent = self._indent (depth)
+               if isinstance (self._c, list):
+                       if len (self._c) == 0:
+                               s.append ('{}matched = true;\n'.format (indent))
+                       elif len (self._c) == 1:
+                               s.append ('{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;\n'.format (indent, next (iter (self._c)), index or ''))
+                       else:
+                               s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index))
+                               s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), len (self._c)))
+                               for i, cp in enumerate (self._c[1:], start=1):
+                                       s.append ('{}0x{:04X}u == buffer->cur ({}).codepoint{}\n'.format (
+                                               self._indent (depth + 2), cp, index + i, ')' if i == len (self._c) - 1 else ' &&'))
+                               s.append ('{}{{\n'.format (indent))
+                               for i in range (len (self._c)):
+                                       s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1)))
+                               s.append ('{}_output_dotted_circle (buffer);\n'.format (self._indent (depth + 1)))
+                               s.append ('{}}}\n'.format (indent))
+               else:
+                       s.append ('{}switch (buffer->cur ({}).codepoint)\n'.format(indent, index or ''))
+                       s.append ('{}{{\n'.format (indent))
+                       cases = collections.defaultdict (set)
+                       for first, rest in sorted (self._c.items ()):
+                               cases[rest.__str__ (index + 1, depth + 2)].add (first)
+                       for body, labels in sorted (cases.items (), key=lambda b_ls: sorted (b_ls[1])[0]):
+                               for i, cp in enumerate (sorted (labels)):
+                                       if i % 4 == 0:
+                                               s.append (self._indent (depth + 1))
+                                       else:
+                                               s.append (' ')
+                                       s.append ('case 0x{:04X}u:{}'.format (cp, '\n' if i % 4 == 3 else ''))
+                               if len (labels) % 4 != 0:
+                                       s.append ('\n')
+                               s.append (body)
+                               s.append ('{}break;\n'.format (self._indent (depth + 2)))
+                       s.append ('{}}}\n'.format (indent))
+               return ''.join (s)
+
+constraints = {}
+with io.open (sys.argv[1], encoding='utf-8') as f:
+       constraints_header = [f.readline ().strip () for i in range (2)]
+       for line in f:
+               j = line.find ('#')
+               if j >= 0:
+                       line = line[:j]
+               constraint = [int (cp, 16) for cp in line.split (';')[0].split ()]
+               if not constraint: continue
+               assert 2 <= len (constraint), 'Prohibited sequence is too short: {}'.format (constraint)
+               script = scripts[constraint[0]]
+               if script in constraints:
+                       constraints[script].add (constraint)
+               else:
+                       constraints[script] = ConstraintSet (constraint)
+               assert constraints, 'No constraints found'
+
+print ('/* == Start of generated functions == */')
+print ('/*')
+print (' * The following functions are generated by running:')
+print (' *')
+print (' *   %s use Scripts.txt' % sys.argv[0])
+print (' *')
+print (' * on files with these headers:')
+print (' *')
+for line in constraints_header:
+       print (' * %s' % line.strip ())
+print (' *')
+for line in scripts_header:
+       print (' * %s' % line.strip ())
+print (' */')
+print ()
+print ('#include "hb-ot-shape-complex-vowel-constraints.hh"')
+print ()
+print ('static void')
+print ('_output_dotted_circle (hb_buffer_t *buffer)')
+print ('{')
+print ('  hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);')
+print ('  _hb_glyph_info_reset_continuation (&dottedcircle);')
+print ('}')
+print ()
+print ('static void')
+print ('_output_with_dotted_circle (hb_buffer_t *buffer)')
+print ('{')
+print ('  _output_dotted_circle (buffer);')
+print ('  buffer->next_glyph ();')
+print ('}')
+print ()
+
+print ('void')
+print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,')
+print ('\t\t\t\t       hb_buffer_t              *buffer,')
+print ('\t\t\t\t       hb_font_t                *font HB_UNUSED)')
+print ('{')
+print ('  /* UGLY UGLY UGLY business of adding dotted-circle in the middle of')
+print ('   * vowel-sequences that look like another vowel.  Data for each script')
+print ('   * collected from the USE script development spec.')
+print ('   *')
+print ('   * https://github.com/harfbuzz/harfbuzz/issues/1019')
+print ('   */')
+print ('  bool processed = false;')
+print ('  buffer->clear_output ();')
+print ('  unsigned int count = buffer->len;')
+print ('  switch ((unsigned) buffer->props.script)')
+print ('  {')
+
+for script, constraints in sorted (constraints.items (), key=lambda s_c: script_order[s_c[0]]):
+       print ('    case HB_SCRIPT_{}:'.format (script.upper ()))
+       print ('      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)')
+       print ('      {')
+       print ('\tbool matched = false;')
+       write (str (constraints))
+       print ('\tbuffer->next_glyph ();')
+       print ('\tif (matched) _output_with_dotted_circle (buffer);')
+       print ('      }')
+       print ('      processed = true;')
+       print ('      break;')
+       print ()
+
+print ('    default:')
+print ('      break;')
+print ('  }')
+print ('  if (processed)')
+print ('  {')
+print ('    if (buffer->idx < count)')
+print ('      buffer->next_glyph ();')
+print ('  }')
+print ('}')
+
+print ()
+print ('/* == End of generated functions == */')
index 87b1572..304410d 100644 (file)
@@ -12,7 +12,11 @@ set(_harfbuzz_libdir "@libdir@")
 string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}")
 set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}")
 while (_harfbuzz_libdir_iter)
+  set(_harfbuzz_libdir_prev_iter "${_harfbuzz_libdir_iter}")
   get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY)
+  if (_harfbuzz_libdir_prev_iter STREQUAL _harfbuzz_libdir_iter)
+    break()
+  endif ()
   get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
 endwhile ()
 unset(_harfbuzz_libdir_iter)
diff --git a/src/hb-aat-fdsc-table.hh b/src/hb-aat-fdsc-table.hh
new file mode 100644 (file)
index 0000000..1188e35
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_FDSC_TABLE_HH
+#define HB_AAT_FDSC_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-open-type.hh"
+
+/*
+ * fdsc -- Font descriptors
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fdsc.html
+ */
+#define HB_AAT_TAG_fdsc HB_TAG('f','d','s','c')
+
+
+namespace AAT {
+
+
+struct FontDescriptor
+{
+  bool has_data () const { return tag; }
+
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  float get_value () const { return u.value.to_float (); }
+
+  enum non_alphabetic_value_t {
+    Alphabetic         = 0,
+    Dingbats           = 1,
+    PiCharacters       = 2,
+    Fleurons           = 3,
+    DecorativeBorders  = 4,
+    InternationalSymbols= 5,
+    MathSymbols                = 6
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  Tag          tag;            /* The 4-byte table tag name. */
+  union {
+  Fixed                value;          /* The value for the descriptor tag. */
+  HBUINT32     nalfType;       /* If the tag is `nalf`, see non_alphabetic_value_t */
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct fdsc
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_fdsc;
+
+  enum {
+    Weight      = HB_TAG ('w','g','h','t'),
+                               /* Percent weight relative to regular weight.
+                                * (defaul value: 1.0) */
+    Width       = HB_TAG ('w','d','t','h'),
+                               /* Percent width relative to regular width.
+                                * (default value: 1.0) */
+    Slant       = HB_TAG ('s','l','n','t'),
+                               /* Angle of slant in degrees, where positive
+                                * is clockwise from straight up.
+                                * (default value: 0.0) */
+    OpticalSize  = HB_TAG ('o','p','s','z'),
+                               /* Point size the font was designed for.
+                                * (default value: 12.0) */
+    NonAlphabetic= HB_TAG ('n','a','l','f')
+                               /* These values are treated as integers,
+                                * not fixed32s. 0 means alphabetic, and greater
+                                * integers mean the font is non-alphabetic (e.g. symbols).
+                                * (default value: 0) */
+  };
+
+  const FontDescriptor &get_descriptor (hb_tag_t style) const
+  { return descriptors.lsearch (style); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 descriptors.sanitize (c));
+  }
+
+  protected:
+  Fixed                version;        /* Version number of the font descriptors
+                                * table (0x00010000 for the current version). */
+  LArrayOf<FontDescriptor>
+               descriptors;    /* List of tagged-coordinate pairs style descriptors
+                                * that will be included to characterize this font.
+                                * Each descriptor consists of a <tag, value> pair.
+                                * These pairs are located in the gxFontDescriptor
+                                * array that follows. */
+  public:
+  DEFINE_SIZE_ARRAY (8, descriptors);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_FDSC_TABLE_HH */
diff --git a/src/hb-aat-fmtx-table.hh b/src/hb-aat-fmtx-table.hh
deleted file mode 100644 (file)
index aa82c88..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  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.
- */
-
-#ifndef HB_AAT_FMTX_TABLE_HH
-#define HB_AAT_FMTX_TABLE_HH
-
-#include "hb-aat-layout-common-private.hh"
-
-/*
- * fmtx -- Font Metrics
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fmtx.html
- */
-#define HB_AAT_TAG_fmtx HB_TAG('f','m','t','x')
-
-
-namespace AAT {
-
-
-struct fmtx
-{
-  static const hb_tag_t tableTag = HB_AAT_TAG_fmtx;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  FixedVersion<>version;               /* Version (set to 0x00020000). */
-  HBUINT32     glyphIndex;             /* The glyph whose points represent the metrics. */
-  HBUINT8      horizontalBefore;       /* Point number for the horizontal ascent. */
-  HBUINT8      horizontalAfter;        /* Point number for the horizontal descent. */
-  HBUINT8      horizontalCaretHead;    /* Point number for the horizontal caret head. */
-  HBUINT8      horizontalCaretBase;    /* Point number for the horizontal caret base. */
-  HBUINT8      verticalBefore;         /* Point number for the vertical ascent. */
-  HBUINT8      verticalAfter;          /* Point number for the vertical descent. */
-  HBUINT8      verticalCaretHead;      /* Point number for the vertical caret head. */
-  HBUINT8      verticalCaretBase;      /* Point number for the vertical caret base. */
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-} /* namespace AAT */
-
-
-#endif /* HB_AAT_FMTX_TABLE_HH */
diff --git a/src/hb-aat-gcid-table.hh b/src/hb-aat-gcid-table.hh
deleted file mode 100644 (file)
index b48a279..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright © 2018  Ebrahim Byagowi
- *
- *  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.
- */
-
-#ifndef HB_AAT_GCID_TABLE_HH
-#define HB_AAT_GCID_TABLE_HH
-
-#include "hb-aat-layout-common-private.hh"
-
-/*
- * gcid -- Glyphs CIDs
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gcid.html
- */
-#define HB_AAT_TAG_gcid HB_TAG('g','c','i','d')
-
-
-namespace AAT {
-
-
-struct gcid
-{
-  static const hb_tag_t tableTag = HB_AAT_TAG_gcid;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && CIDs.sanitize (c)));
-  }
-
-  protected:
-  HBUINT16     version;        /* Version number (set to 0) */
-  HBUINT16     format;         /* Data format (set to 0) */
-  HBUINT32     size;           /* Size of the table, including header */
-  HBUINT16     registry;       /* The registry ID */
-  HBUINT8      registryName[64];
-                               /* The registry name in ASCII */
-  HBUINT16     order;          /* The order ID */
-  HBUINT8      orderName[64];  /* The order name in ASCII */
-  HBUINT16     supplementVersion;
-                               /* The supplement version */
-  ArrayOf<HBUINT16>
-               CIDs;           /* The CIDs for the glyphs in the font,
-                                * starting with glyph 0. If a glyph does not correspond
-                                * to a CID in the identified collection, 0xFFFF is used.
-                                * This should not exceed the number of glyphs in the font. */
-  public:
-  DEFINE_SIZE_ARRAY (144, CIDs);
-};
-
-} /* namespace AAT */
-
-
-#endif /* HB_AAT_GCID_TABLE_HH */
index 3b7912b..236e4aa 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_AAT_LAYOUT_ANKR_TABLE_HH
 #define HB_AAT_LAYOUT_ANKR_TABLE_HH
 
-#include "hb-aat-layout-common-private.hh"
+#include "hb-aat-layout-common.hh"
 
 /*
  * ankr -- Anchor Point
 
 namespace AAT {
 
+using namespace OT;
+
 
 struct Anchor
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
+  public:
   FWORD                xCoordinate;
   FWORD                yCoordinate;
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
+typedef LArrayOf<Anchor> GlyphAnchors;
+
 struct ankr
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_ankr;
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ankr;
+
+  const Anchor &get_anchor (hb_codepoint_t glyph_id,
+                           unsigned int i,
+                           unsigned int num_glyphs) const
+  {
+    const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
+    if (!offset)
+      return Null(Anchor);
+    const GlyphAnchors &anchors = &(this+anchorData) + *offset;
+    return anchors[i];
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
                          version == 0 &&
-                         lookupTable.sanitize (c, this) &&
-                         anchors.sanitize (c, this)));
+                         lookupTable.sanitize (c, this, &(this+anchorData))));
   }
 
   protected:
   HBUINT16     version;        /* Version number (set to zero) */
   HBUINT16     flags;          /* Flags (currently unused; set to zero) */
-  LOffsetTo<Lookup<HBUINT16> >
+  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors> > >
                lookupTable;    /* Offset to the table's lookup table */
-  LOffsetTo<LArrayOf<Anchor> >
-               anchors;        /* Offset to the glyph data table */
+  LNNOffsetTo<HBUINT8>
+               anchorData;     /* Offset to the glyph data table */
 
   public:
   DEFINE_SIZE_STATIC (12);
index df2bf5b..9139d28 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_AAT_LAYOUT_BSLN_TABLE_HH
 #define HB_AAT_LAYOUT_BSLN_TABLE_HH
 
-#include "hb-aat-layout-common-private.hh"
+#include "hb-aat-layout-common.hh"
 
 /*
  * bsln -- Baseline
@@ -39,7 +39,7 @@ namespace AAT {
 
 struct BaselineTableFormat0Part
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
@@ -57,7 +57,7 @@ struct BaselineTableFormat0Part
 
 struct BaselineTableFormat1Part
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
@@ -75,7 +75,7 @@ struct BaselineTableFormat1Part
 
 struct BaselineTableFormat2Part
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
@@ -98,7 +98,7 @@ struct BaselineTableFormat2Part
 
 struct BaselineTableFormat3Part
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && lookupTable.sanitize (c));
@@ -116,15 +116,16 @@ struct BaselineTableFormat3Part
 
 struct bsln
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_bsln;
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_bsln;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
       return_trace (false);
 
-    switch (format) {
+    switch (format)
+    {
     case 0: return_trace (parts.format0.sanitize (c));
     case 1: return_trace (parts.format1.sanitize (c));
     case 2: return_trace (parts.format2.sanitize (c));
diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
deleted file mode 100644 (file)
index 2825b18..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_AAT_LAYOUT_COMMON_PRIVATE_HH
-#define HB_AAT_LAYOUT_COMMON_PRIVATE_HH
-
-#include "hb-aat-layout-private.hh"
-
-
-namespace AAT {
-
-using namespace OT;
-
-
-/*
- * Binary Searching Tables
- */
-
-struct BinSearchHeader
-{
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16     unitSize;       /* Size of a lookup unit for this search in bytes. */
-  HBUINT16     nUnits;         /* Number of units of the preceding size to be searched. */
-  HBUINT16     searchRange;    /* The value of unitSize times the largest power of 2
-                                * that is less than or equal to the value of nUnits. */
-  HBUINT16     entrySelector;  /* The log base 2 of the largest power of 2 less than
-                                * or equal to the value of nUnits. */
-  HBUINT16     rangeShift;     /* The value of unitSize times the difference of the
-                                * value of nUnits minus the largest power of 2 less
-                                * than or equal to the value of nUnits. */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-template <typename Type>
-struct BinSearchArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= header.nUnits)) return Null(Type);
-    return StructAtOffset<Type> (bytesZ, i * header.unitSize);
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    return StructAtOffset<Type> (bytesZ, i * header.unitSize);
-  }
-  inline unsigned int get_size (void) const
-  { return header.static_size + header.nUnits * header.unitSize; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && StructAtOffset<Type> (bytesZ, 0).sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = header.nUnits;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!(*this)[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  template <typename T>
-  inline const Type *bsearch (const T &key) const
-  {
-    unsigned int size = header.unitSize;
-    int min = 0, max = (int) header.nUnits - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      const Type *p = (const Type *) (((const char *) bytesZ) + (mid * size));
-      int c = p->cmp (key);
-      if (c < 0)
-       max = mid - 1;
-      else if (c > 0)
-       min = mid + 1;
-      else
-       return p;
-    }
-    return nullptr;
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (header.sanitize (c) &&
-                 Type::static_size >= header.unitSize &&
-                 c->check_array (bytesZ, header.unitSize, header.nUnits));
-  }
-
-  protected:
-  BinSearchHeader      header;
-  HBUINT8              bytesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (10, bytesZ);
-};
-
-
-/*
- * Lookup Table
- */
-
-template <typename T> struct Lookup;
-
-template <typename T>
-struct LookupFormat0
-{
-  friend struct Lookup<T>;
-
-  private:
-  inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
-  {
-    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
-    return &arrayZ[glyph_id];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (arrayZ.sanitize (c, c->num_glyphs));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 0 */
-  UnsizedArrayOf<T>
-               arrayZ;         /* Array of lookup values, indexed by glyph index. */
-  public:
-  DEFINE_SIZE_ARRAY (2, arrayZ);
-};
-
-
-template <typename T>
-struct LookupSegmentSingle
-{
-  inline int cmp (hb_codepoint_t g) const {
-    return g < first ? -1 : g <= last ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && value.sanitize (c));
-  }
-
-  GlyphID      last;           /* Last GlyphID in this segment */
-  GlyphID      first;          /* First GlyphID in this segment */
-  T            value;          /* The lookup value (only one) */
-  public:
-  DEFINE_SIZE_STATIC (4 + T::static_size);
-};
-
-template <typename T>
-struct LookupFormat2
-{
-  friend struct Lookup<T>;
-
-  private:
-  inline const T* get_value (hb_codepoint_t glyph_id) const
-  {
-    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
-    return v ? &v->value : nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (segments.sanitize (c));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 2 */
-  BinSearchArrayOf<LookupSegmentSingle<T> >
-               segments;       /* The actual segments. These must already be sorted,
-                                * according to the first word in each one (the last
-                                * glyph in each segment). */
-  public:
-  DEFINE_SIZE_ARRAY (8, segments);
-};
-
-template <typename T>
-struct LookupSegmentArray
-{
-  inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
-  {
-    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
-  }
-
-  inline int cmp (hb_codepoint_t g) const {
-    return g < first ? -1 : g <= last ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 first <= last &&
-                 valuesZ.sanitize (c, base, last - first + 1));
-  }
-
-  GlyphID      last;           /* Last GlyphID in this segment */
-  GlyphID      first;          /* First GlyphID in this segment */
-  OffsetTo<UnsizedArrayOf<T> >
-               valuesZ;        /* A 16-bit offset from the start of
-                                * the table to the data. */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename T>
-struct LookupFormat4
-{
-  friend struct Lookup<T>;
-
-  private:
-  inline const T* get_value (hb_codepoint_t glyph_id) const
-  {
-    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
-    return v ? v->get_value (glyph_id, this) : nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (segments.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 2 */
-  BinSearchArrayOf<LookupSegmentArray<T> >
-               segments;       /* The actual segments. These must already be sorted,
-                                * according to the first word in each one (the last
-                                * glyph in each segment). */
-  public:
-  DEFINE_SIZE_ARRAY (8, segments);
-};
-
-template <typename T>
-struct LookupSingle
-{
-  inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && value.sanitize (c));
-  }
-
-  GlyphID      glyph;          /* Last GlyphID */
-  T            value;          /* The lookup value (only one) */
-  public:
-  DEFINE_SIZE_STATIC (4 + T::static_size);
-};
-
-template <typename T>
-struct LookupFormat6
-{
-  friend struct Lookup<T>;
-
-  private:
-  inline const T* get_value (hb_codepoint_t glyph_id) const
-  {
-    const LookupSingle<T> *v = entries.bsearch (glyph_id);
-    return v ? &v->value : nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (entries.sanitize (c));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 6 */
-  BinSearchArrayOf<LookupSingle<T> >
-               entries;        /* The actual entries, sorted by glyph index. */
-  public:
-  DEFINE_SIZE_ARRAY (8, entries);
-};
-
-template <typename T>
-struct LookupFormat8
-{
-  friend struct Lookup<T>;
-
-  private:
-  inline const T* get_value (hb_codepoint_t glyph_id) const
-  {
-    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? &valueArrayZ[glyph_id - firstGlyph] : nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 6 */
-  GlyphID      firstGlyph;     /* First glyph index included in the trimmed array. */
-  HBUINT16     glyphCount;     /* Total number of glyphs (equivalent to the last
-                                * glyph minus the value of firstGlyph plus 1). */
-  UnsizedArrayOf<T>
-               valueArrayZ;    /* The lookup values (indexed by the glyph index
-                                * minus the value of firstGlyph). */
-  public:
-  DEFINE_SIZE_ARRAY (6, valueArrayZ);
-};
-
-template <typename T>
-struct Lookup
-{
-  inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
-  {
-    switch (u.format) {
-    case 0: return u.format0.get_value (glyph_id, num_glyphs);
-    case 2: return u.format2.get_value (glyph_id);
-    case 4: return u.format4.get_value (glyph_id);
-    case 6: return u.format6.get_value (glyph_id);
-    case 8: return u.format8.get_value (glyph_id);
-    default:return nullptr;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 4: return_trace (u.format4.sanitize (c));
-    case 6: return_trace (u.format6.sanitize (c));
-    case 8: return_trace (u.format8.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  LookupFormat0<T>     format0;
-  LookupFormat2<T>     format2;
-  LookupFormat4<T>     format4;
-  LookupFormat6<T>     format6;
-  LookupFormat8<T>     format8;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Extended State Table
- */
-
-template <typename T>
-struct Entry
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    /* Note, we don't recurse-sanitize data because we don't access it.
-     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
-     * which ensures that data has a simple sanitize(). To be determined
-     * if I need to remove that as well. */
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  HBUINT16     newState;       /* Byte offset from beginning of state table
-                                * to the new state. Really?!?! Or just state
-                                * number?  The latter in morx for sure. */
-  HBUINT16     flags;          /* Table specific. */
-  T            data;           /* Optional offsets to per-glyph tables. */
-  public:
-  DEFINE_SIZE_STATIC (4 + T::static_size);
-};
-
-template <>
-struct Entry<void>
-{
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  public:
-  HBUINT16     newState;       /* Byte offset from beginning of state table to the new state. */
-  HBUINT16     flags;          /* Table specific. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-template <typename Extra>
-struct StateTable
-{
-  inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
-  {
-    const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
-    return v ? *v : 1;
-  }
-
-  inline const Entry<Extra> *get_entries () const
-  {
-    return (this+entryTable).arrayZ;
-  }
-
-  inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const
-  {
-    if (unlikely (klass >= nClasses)) return nullptr;
-
-    const HBUINT16 *states = (this+stateArrayTable).arrayZ;
-    const Entry<Extra> *entries = (this+entryTable).arrayZ;
-
-    unsigned int entry = states[state * nClasses + klass];
-
-    return &entries[entry];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       unsigned int *num_entries_out = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) &&
-                   classTable.sanitize (c, this)))) return_trace (false);
-
-    const HBUINT16 *states = (this+stateArrayTable).arrayZ;
-    const Entry<Extra> *entries = (this+entryTable).arrayZ;
-
-    unsigned int num_states = 1;
-    unsigned int num_entries = 0;
-
-    unsigned int state = 0;
-    unsigned int entry = 0;
-    while (state < num_states)
-    {
-      if (unlikely (!c->check_array (states,
-                                    states[0].static_size * nClasses,
-                                    num_states)))
-       return_trace (false);
-      { /* Sweep new states. */
-       const HBUINT16 *stop = &states[num_states * nClasses];
-       for (const HBUINT16 *p = &states[state * nClasses]; p < stop; p++)
-         num_entries = MAX<unsigned int> (num_entries, *p + 1);
-       state = num_states;
-      }
-
-      if (unlikely (!c->check_array (entries,
-                                    entries[0].static_size,
-                                    num_entries)))
-       return_trace (false);
-      { /* Sweep new entries. */
-       const Entry<Extra> *stop = &entries[num_entries];
-       for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
-         num_states = MAX<unsigned int> (num_states, p->newState + 1);
-       entry = num_entries;
-      }
-    }
-
-    if (num_entries_out)
-      *num_entries_out = num_entries;
-
-    return_trace (true);
-  }
-
-  protected:
-  HBUINT32     nClasses;       /* Number of classes, which is the number of indices
-                                * in a single line in the state array. */
-  LOffsetTo<Lookup<HBUINT16> >
-               classTable;     /* Offset to the class table. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-               stateArrayTable;/* Offset to the state array. */
-  LOffsetTo<UnsizedArrayOf<Entry<Extra> > >
-               entryTable;     /* Offset to the entry array. */
-
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-template <typename EntryData>
-struct StateTableDriver
-{
-  inline StateTableDriver (const StateTable<EntryData> &machine_,
-                          hb_buffer_t *buffer_,
-                          hb_face_t *face_) :
-             machine (machine_),
-             buffer (buffer_),
-             num_glyphs (face_->get_num_glyphs ()) {}
-
-  template <typename context_t>
-  inline void drive (context_t *c)
-  {
-    hb_glyph_info_t *info = buffer->info;
-
-    if (!c->in_place)
-      buffer->clear_output ();
-
-    unsigned int state = 0;
-    bool last_was_dont_advance = false;
-    for (buffer->idx = 0;;)
-    {
-      unsigned int klass = buffer->idx < buffer->len ?
-                          machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
-                          0 /* End of text */;
-      const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
-      if (unlikely (!entry))
-       break;
-
-      /* Unsafe-to-break before this if not in state 0, as things might
-       * go differently if we start from state 0 here. */
-      if (state && buffer->idx)
-      {
-       /* If there's no action and we're just epsilon-transitioning to state 0,
-        * safe to break. */
-       if (c->is_actionable (this, entry) ||
-           !(entry->newState == 0 && entry->flags == context_t::DontAdvance))
-         buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1);
-      }
-
-      /* Unsafe-to-break if end-of-text would kick in here. */
-      if (buffer->idx + 2 <= buffer->len)
-      {
-       const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
-       if (c->is_actionable (this, end_entry))
-         buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
-      }
-
-      if (unlikely (!c->transition (this, entry)))
-        break;
-
-      last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
-
-      state = entry->newState;
-
-      if (buffer->idx == buffer->len)
-        break;
-
-      if (!last_was_dont_advance)
-        buffer->next_glyph ();
-    }
-
-    if (!c->in_place)
-    {
-      for (; buffer->idx < buffer->len;)
-        buffer->next_glyph ();
-      buffer->swap_buffers ();
-    }
-  }
-
-  public:
-  const StateTable<EntryData> &machine;
-  hb_buffer_t *buffer;
-  unsigned int num_glyphs;
-};
-
-
-
-struct hb_aat_apply_context_t :
-       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
-{
-  inline const char *get_name (void) { return "APPLY"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  hb_sanitize_context_t sanitizer;
-
-  /* Unused. For debug tracing only. */
-  unsigned int lookup_index;
-  unsigned int debug_depth;
-
-  inline hb_aat_apply_context_t (hb_font_t *font_,
-                                hb_buffer_t *buffer_,
-                                hb_blob_t *table) :
-               font (font_), face (font->face), buffer (buffer_),
-               sanitizer (), lookup_index (0), debug_depth (0)
-  {
-    sanitizer.init (table);
-    sanitizer.num_glyphs = face->get_num_glyphs ();
-    sanitizer.start_processing ();
-  }
-
-  inline void set_lookup_index (unsigned int i) { lookup_index = i; }
-
-  inline ~hb_aat_apply_context_t (void)
-  {
-    sanitizer.end_processing ();
-  }
-};
-
-
-} /* namespace AAT */
-
-
-#endif /* HB_AAT_LAYOUT_COMMON_PRIVATE_HH */
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
new file mode 100644 (file)
index 0000000..27ade28
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_COMMON_HH
+#define HB_AAT_LAYOUT_COMMON_HH
+
+#include "hb-aat-layout.hh"
+#include "hb-open-type.hh"
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+/*
+ * Lookup Table
+ */
+
+template <typename T> struct Lookup;
+
+template <typename T>
+struct LookupFormat0
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
+    return &arrayZ[glyph_id];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 0 */
+  UnsizedArrayOf<T>
+               arrayZ;         /* Array of lookup values, indexed by glyph index. */
+  public:
+  DEFINE_SIZE_UNBOUNDED (2);
+};
+
+
+template <typename T>
+struct LookupSegmentSingle
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1 ; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID      last;           /* Last GlyphID in this segment */
+  GlyphID      first;          /* First GlyphID in this segment */
+  T            value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat2
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 2 */
+  VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
+               segments;       /* The actual segments. These must already be sorted,
+                                * according to the first word in each one (the last
+                                * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSegmentArray
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  const T* get_value (hb_codepoint_t glyph_id, const void *base) const
+  {
+    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
+  }
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 first <= last &&
+                 valuesZ.sanitize (c, base, last - first + 1));
+  }
+  template <typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 first <= last &&
+                 valuesZ.sanitize (c, base, last - first + 1, user_data));
+  }
+
+  GlyphID      last;           /* Last GlyphID in this segment */
+  GlyphID      first;          /* First GlyphID in this segment */
+  NNOffsetTo<UnsizedArrayOf<T> >
+               valuesZ;        /* A 16-bit offset from the start of
+                                * the table to the data. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename T>
+struct LookupFormat4
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
+    return v ? v->get_value (glyph_id, this) : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this, base));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 4 */
+  VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
+               segments;       /* The actual segments. These must already be sorted,
+                                * according to the first word in each one (the last
+                                * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSingle
+{
+  static constexpr unsigned TerminationWordCount = 1u;
+
+  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID      glyph;          /* Last GlyphID */
+  T            value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (2 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat6
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSingle<T> *v = entries.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 6 */
+  VarSizedBinSearchArrayOf<LookupSingle<T> >
+               entries;        /* The actual entries, sorted by glyph index. */
+  public:
+  DEFINE_SIZE_ARRAY (8, entries);
+};
+
+template <typename T>
+struct LookupFormat8
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
+          &valueArrayZ[glyph_id - firstGlyph] : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 8 */
+  GlyphID      firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16     glyphCount;     /* Total number of glyphs (equivalent to the last
+                                * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<T>
+               valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (6, valueArrayZ);
+};
+
+template <typename T>
+struct LookupFormat10
+{
+  friend struct Lookup<T>;
+
+  private:
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
+  {
+    if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
+      return Null(T);
+
+    const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
+
+    unsigned int v = 0;
+    unsigned int count = valueSize;
+    for (unsigned int i = 0; i < count; i++)
+      v = (v << 8) | *p++;
+
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 valueSize <= 4 &&
+                 valueArrayZ.sanitize (c, glyphCount * valueSize));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 8 */
+  HBUINT16     valueSize;      /* Byte size of each value. */
+  GlyphID      firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16     glyphCount;     /* Total number of glyphs (equivalent to the last
+                                * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<HBUINT8>
+               valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (8, valueArrayZ);
+};
+
+template <typename T>
+struct Lookup
+{
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_value (glyph_id, num_glyphs);
+    case 2: return u.format2.get_value (glyph_id);
+    case 4: return u.format4.get_value (glyph_id);
+    case 6: return u.format6.get_value (glyph_id);
+    case 8: return u.format8.get_value (glyph_id);
+    default:return nullptr;
+    }
+  }
+
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+      /* Format 10 cannot return a pointer. */
+      case 10: return u.format10.get_value_or_null (glyph_id);
+      default:
+      const T *v = get_value (glyph_id, num_glyphs);
+      return v ? *v : Null(T);
+    }
+  }
+
+  typename T::type get_class (hb_codepoint_t glyph_id,
+                             unsigned int num_glyphs,
+                             unsigned int outOfRange) const
+  {
+    const T *v = get_value (glyph_id, num_glyphs);
+    return v ? *v : outOfRange;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 4: return_trace (u.format4.sanitize (c));
+    case 6: return_trace (u.format6.sanitize (c));
+    case 8: return_trace (u.format8.sanitize (c));
+    case 10: return_trace (u.format10.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c, base));
+    case 2: return_trace (u.format2.sanitize (c, base));
+    case 4: return_trace (u.format4.sanitize (c, base));
+    case 6: return_trace (u.format6.sanitize (c, base));
+    case 8: return_trace (u.format8.sanitize (c, base));
+    case 10: return_trace (false); /* We don't support format10 here currently. */
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  LookupFormat0<T>     format0;
+  LookupFormat2<T>     format2;
+  LookupFormat4<T>     format4;
+  LookupFormat6<T>     format6;
+  LookupFormat8<T>     format8;
+  LookupFormat10<T>    format10;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+/* Lookup 0 has unbounded size (dependant on num_glyphs).  So we need to defined
+ * special NULL objects for Lookup<> objects, but since it's template our macros
+ * don't work.  So we have to hand-code them here.  UGLY. */
+} /* Close namespace. */
+/* Ugly hand-coded null objects for template Lookup<> :(. */
+extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup); }
+namespace AAT {
+
+enum { DELETED_GLYPH = 0xFFFF };
+
+/*
+ * (Extended) State Table
+ */
+
+template <typename T>
+struct Entry
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    /* Note, we don't recurse-sanitize data because we don't access it.
+     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
+     * which ensures that data has a simple sanitize(). To be determined
+     * if I need to remove that as well.
+     *
+     * HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
+     * assertion wouldn't be checked, hence the line below. */
+    static_assert (T::static_size, "");
+
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16     newState;       /* Byte offset from beginning of state table
+                                * to the new state. Really?!?! Or just state
+                                * number?  The latter in morx for sure. */
+  HBUINT16     flags;          /* Table specific. */
+  T            data;           /* Optional offsets to per-glyph tables. */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <>
+struct Entry<void>
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16     newState;       /* Byte offset from beginning of state table to the new state. */
+  HBUINT16     flags;          /* Table specific. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename Types, typename Extra>
+struct StateTable
+{
+  typedef typename Types::HBUINT HBUINT;
+  typedef typename Types::HBUSHORT HBUSHORT;
+  typedef typename Types::ClassTypeNarrow ClassType;
+
+  enum State
+  {
+    STATE_START_OF_TEXT = 0,
+    STATE_START_OF_LINE = 1,
+  };
+  enum Class
+  {
+    CLASS_END_OF_TEXT = 0,
+    CLASS_OUT_OF_BOUNDS = 1,
+    CLASS_DELETED_GLYPH = 2,
+    CLASS_END_OF_LINE = 3,
+  };
+
+  int new_state (unsigned int newState) const
+  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
+
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
+    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+  }
+
+  const Entry<Extra> *get_entries () const
+  { return (this+entryTable).arrayZ; }
+
+  const Entry<Extra> &get_entry (int state, unsigned int klass) const
+  {
+    if (unlikely (klass >= nClasses))
+      klass = StateTable<Types, Entry<Extra> >::CLASS_OUT_OF_BOUNDS;
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int entry = states[state * nClasses + klass];
+    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
+
+    return entries[entry];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                unsigned int *num_entries_out = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) &&
+                   nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
+                   classTable.sanitize (c, this)))) return_trace (false);
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int num_classes = nClasses;
+    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
+      return_trace (false);
+    unsigned int row_stride = num_classes * states[0].static_size;
+
+    /* Apple 'kern' table has this peculiarity:
+     *
+     * "Because the stateTableOffset in the state table header is (strictly
+     * speaking) redundant, some 'kern' tables use it to record an initial
+     * state where that should not be StartOfText. To determine if this is
+     * done, calculate what the stateTableOffset should be. If it's different
+     * from the actual stateTableOffset, use it as the initial state."
+     *
+     * We implement this by calling the initial state zero, but allow *negative*
+     * states if the start state indeed was not the first state.  Since the code
+     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
+     * tables are not affected since those address states by index, not offset.
+     */
+
+    int min_state = 0;
+    int max_state = 0;
+    unsigned int num_entries = 0;
+
+    int state_pos = 0;
+    int state_neg = 0;
+    unsigned int entry = 0;
+    while (min_state < state_neg || state_pos <= max_state)
+    {
+      if (min_state < state_neg)
+      {
+       /* Negative states. */
+       if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
+         return_trace (false);
+       if (unlikely (!c->check_range (&states[min_state * num_classes],
+                                      -min_state,
+                                      row_stride)))
+         return_trace (false);
+       if ((c->max_ops -= state_neg - min_state) <= 0)
+         return_trace (false);
+       { /* Sweep new states. */
+         const HBUSHORT *stop = &states[min_state * num_classes];
+         if (unlikely (stop > states))
+           return_trace (false);
+         for (const HBUSHORT *p = states; stop < p; p--)
+           num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
+         state_neg = min_state;
+       }
+      }
+
+      if (state_pos <= max_state)
+      {
+       /* Positive states. */
+       if (unlikely (!c->check_range (states,
+                                      max_state + 1,
+                                      row_stride)))
+         return_trace (false);
+       if ((c->max_ops -= max_state - state_pos + 1) <= 0)
+         return_trace (false);
+       { /* Sweep new states. */
+         if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
+           return_trace (false);
+         const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
+         if (unlikely (stop < states))
+           return_trace (false);
+         for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
+           num_entries = MAX<unsigned int> (num_entries, *p + 1);
+         state_pos = max_state + 1;
+       }
+      }
+
+      if (unlikely (!c->check_array (entries, num_entries)))
+       return_trace (false);
+      if ((c->max_ops -= num_entries - entry) <= 0)
+       return_trace (false);
+      { /* Sweep new entries. */
+       const Entry<Extra> *stop = &entries[num_entries];
+       for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
+       {
+         int newState = new_state (p->newState);
+         min_state = MIN (min_state, newState);
+         max_state = MAX (max_state, newState);
+       }
+       entry = num_entries;
+      }
+    }
+
+    if (num_entries_out)
+      *num_entries_out = num_entries;
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT       nClasses;       /* Number of classes, which is the number of indices
+                                * in a single line in the state array. */
+  NNOffsetTo<ClassType, HBUINT>
+               classTable;     /* Offset to the class table. */
+  NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
+               stateArrayTable;/* Offset to the state array. */
+  NNOffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
+               entryTable;     /* Offset to the entry array. */
+
+  public:
+  DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
+};
+
+template <typename HBUCHAR>
+struct ClassTable
+{
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
+  {
+    unsigned int i = glyph_id - firstGlyph;
+    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
+  }
+  unsigned int get_class (hb_codepoint_t glyph_id,
+                         unsigned int num_glyphs HB_UNUSED,
+                         unsigned int outOfRange) const
+  {
+    return get_class (glyph_id, outOfRange);
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classArray.sanitize (c));
+  }
+  protected:
+  GlyphID              firstGlyph;     /* First glyph index included in the trimmed array. */
+  ArrayOf<HBUCHAR>     classArray;     /* The class codes (indexed by glyph index minus
+                                        * firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (4, classArray);
+};
+
+struct ObsoleteTypes
+{
+  static constexpr bool extended = false;
+  typedef HBUINT16 HBUINT;
+  typedef HBUINT8 HBUSHORT;
+  typedef ClassTable<HBUINT8> ClassTypeNarrow;
+  typedef ClassTable<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                    const void *base,
+                                    const T *array)
+  {
+    return (offset - ((const char *) array - (const char *) base)) / sizeof (T);
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                        const void *base,
+                                        const T *array)
+  {
+    return offsetToIndex (offset, base, array);
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                        const void *base,
+                                        const T *array)
+  {
+    return offsetToIndex (2 * offset, base, array);
+  }
+};
+struct ExtendedTypes
+{
+  static constexpr bool extended = true;
+  typedef HBUINT32 HBUINT;
+  typedef HBUINT16 HBUSHORT;
+  typedef Lookup<HBUINT16> ClassTypeNarrow;
+  typedef Lookup<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                    const void *base HB_UNUSED,
+                                    const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                        const void *base HB_UNUSED,
+                                        const T *array HB_UNUSED)
+  {
+    return offset / 2;
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                        const void *base HB_UNUSED,
+                                        const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+};
+
+template <typename Types, typename EntryData>
+struct StateTableDriver
+{
+  StateTableDriver (const StateTable<Types, EntryData> &machine_,
+                   hb_buffer_t *buffer_,
+                   hb_face_t *face_) :
+             machine (machine_),
+             buffer (buffer_),
+             num_glyphs (face_->get_num_glyphs ()) {}
+
+  template <typename context_t>
+  void drive (context_t *c)
+  {
+    if (!c->in_place)
+      buffer->clear_output ();
+
+    int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
+    for (buffer->idx = 0; buffer->successful;)
+    {
+      unsigned int klass = buffer->idx < buffer->len ?
+                          machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
+                          (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
+      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
+      const Entry<EntryData> &entry = machine.get_entry (state, klass);
+
+      /* Unsafe-to-break before this if not in state 0, as things might
+       * go differently if we start from state 0 here.
+       *
+       * Ugh.  The indexing here is ugly... */
+      if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
+      {
+       /* If there's no action and we're just epsilon-transitioning to state 0,
+        * safe to break. */
+       if (c->is_actionable (this, entry) ||
+           !(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
+             entry.flags == context_t::DontAdvance))
+         buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
+      }
+
+      /* Unsafe-to-break if end-of-text would kick in here. */
+      if (buffer->idx + 2 <= buffer->len)
+      {
+       const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
+       if (c->is_actionable (this, end_entry))
+         buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
+      }
+
+      c->transition (this, entry);
+
+      state = machine.new_state (entry.newState);
+      DEBUG_MSG (APPLY, nullptr, "s%d", state);
+
+      if (buffer->idx == buffer->len)
+       break;
+
+      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
+       buffer->next_glyph ();
+    }
+
+    if (!c->in_place)
+    {
+      for (; buffer->successful && buffer->idx < buffer->len;)
+       buffer->next_glyph ();
+      buffer->swap_buffers ();
+    }
+  }
+
+  public:
+  const StateTable<Types, EntryData> &machine;
+  hb_buffer_t *buffer;
+  unsigned int num_glyphs;
+};
+
+
+struct ankr;
+
+struct hb_aat_apply_context_t :
+       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  const char *get_name () { return "APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_ot_shape_plan_t *plan;
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  hb_sanitize_context_t sanitizer;
+  const ankr *ankr_table;
+
+  /* Unused. For debug tracing only. */
+  unsigned int lookup_index;
+  unsigned int debug_depth;
+
+  HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+                                     hb_font_t *font_,
+                                     hb_buffer_t *buffer_,
+                                     hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)));
+
+  HB_INTERNAL ~hb_aat_apply_context_t ();
+
+  HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
+
+  void set_lookup_index (unsigned int i) { lookup_index = i; }
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_COMMON_HH */
index 3e070d7..ab23ee0 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_AAT_LAYOUT_FEAT_TABLE_HH
 #define HB_AAT_LAYOUT_FEAT_TABLE_HH
 
-#include "hb-aat-layout-common-private.hh"
+#include "hb-aat-layout-common.hh"
 
 /*
  * feat -- Feature Name
@@ -39,7 +39,28 @@ namespace AAT {
 
 struct SettingName
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  friend struct FeatureName;
+
+  int cmp (hb_aat_layout_feature_selector_t key) const
+  { return (int) key - (int) setting; }
+
+  hb_aat_layout_feature_selector_t get_selector () const
+  { return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
+
+  void get_info (hb_aat_layout_feature_selector_info_t *s,
+                       hb_aat_layout_feature_selector_t default_selector) const
+  {
+    s->name_id = nameIndex;
+
+    s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
+    s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
+                (hb_aat_layout_feature_selector_t) (s->enable + 1) :
+                default_selector;
+
+    s->reserved = 0;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
@@ -51,35 +72,75 @@ struct SettingName
   public:
   DEFINE_SIZE_STATIC (4);
 };
+DECLARE_NULL_NAMESPACE_BYTES (AAT, SettingName);
+
+struct feat;
 
 struct FeatureName
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         (base+settingTable).sanitize (c, nSettings)));
-  }
+  int cmp (hb_aat_layout_feature_type_t key) const
+  { return (int) key - (int) feature; }
 
   enum {
-    Exclusive = 0x8000,                /* If set, the feature settings are mutually exclusive. */
-    NotDefault = 0x4000,       /* If clear, then the setting with an index of 0 in
+    Exclusive  = 0x8000,       /* If set, the feature settings are mutually exclusive. */
+    NotDefault = 0x4000,       /* If clear, then the setting with an index of 0 in
                                 * the setting name array for this feature should
                                 * be taken as the default for the feature
                                 * (if one is required). If set, then bits 0-15 of this
                                 * featureFlags field contain the index of the setting
                                 * which is to be taken as the default. */
-    IndexMask = 0x00FF         /* If bits 30 and 31 are set, then these sixteen bits
+    IndexMask  = 0x00FF        /* If bits 30 and 31 are set, then these sixteen bits
                                 * indicate the index of the setting in the setting name
                                 * array for this feature which should be taken
                                 * as the default. */
   };
 
+  unsigned int get_selector_infos (unsigned int                           start_offset,
+                                  unsigned int                          *selectors_count, /* IN/OUT.  May be NULL. */
+                                  hb_aat_layout_feature_selector_info_t *selectors,       /* OUT.     May be NULL. */
+                                  unsigned int                          *pdefault_index,  /* OUT.     May be NULL. */
+                                  const void *base) const
+  {
+    hb_array_t< const SettingName> settings_table = (base+settingTableZ).as_array (nSettings);
+
+    static_assert (Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, "");
+
+    hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID;
+    unsigned int default_index = Index::NOT_FOUND_INDEX;
+    if (featureFlags & Exclusive)
+    {
+      default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0;
+      default_selector = settings_table[default_index].get_selector ();
+    }
+    if (pdefault_index)
+      *pdefault_index = default_index;
+
+    if (selectors_count)
+    {
+      hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
+      for (unsigned int i = 0; i < arr.length; i++)
+        settings_table[start_offset + i].get_info (&selectors[i], default_selector);
+    }
+    return settings_table.length;
+  }
+
+  hb_aat_layout_feature_type_t get_feature_type () const
+  { return (hb_aat_layout_feature_type_t) (unsigned int) feature; }
+
+  hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         (base+settingTableZ).sanitize (c, nSettings)));
+  }
+
   protected:
   HBUINT16     feature;        /* Feature type. */
   HBUINT16     nSettings;      /* The number of records in the setting name array. */
-  LOffsetTo<UnsizedArrayOf<SettingName> >
-               settingTable  /* Offset in bytes from the beginning of this table to
+  LOffsetTo<UnsizedArrayOf<SettingName>, false>
+               settingTableZ;  /* Offset in bytes from the beginning of this table to
                                 * this feature's setting name array. The actual type of
                                 * record this offset refers to will depend on the
                                 * exclusivity value, as described below. */
@@ -93,13 +154,49 @@ struct FeatureName
 
 struct feat
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_feat;
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat;
+
+  bool has_data () const { return version.to_int (); }
+
+  unsigned int get_feature_types (unsigned int                  start_offset,
+                                 unsigned int                 *count,
+                                 hb_aat_layout_feature_type_t *features) const
+  {
+    unsigned int feature_count = featureNameCount;
+    if (count && *count)
+    {
+      unsigned int len = MIN (feature_count - start_offset, *count);
+      for (unsigned int i = 0; i < len; i++)
+       features[i] = namesZ[i + start_offset].get_feature_type ();
+      *count = len;
+    }
+    return featureNameCount;
+  }
+
+  const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
+  {
+    return namesZ.bsearch (featureNameCount, feature_type);
+  }
+
+  hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
+  { return get_feature (feature).get_feature_name_id (); }
+
+  unsigned int get_selector_infos (hb_aat_layout_feature_type_t           feature_type,
+                                  unsigned int                           start_offset,
+                                  unsigned int                          *selectors_count, /* IN/OUT.  May be NULL. */
+                                  hb_aat_layout_feature_selector_info_t *selectors,       /* OUT.     May be NULL. */
+                                  unsigned int                          *default_index    /* OUT.     May be NULL. */) const
+  {
+    return get_feature (feature_type).get_selector_infos (start_offset, selectors_count, selectors,
+                                                         default_index, this);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                         names.sanitize (c, featureNameCount, this)));
+                         version.major == 1 &&
+                         namesZ.sanitize (c, featureNameCount, this)));
   }
 
   protected:
@@ -109,8 +206,8 @@ struct feat
                                /* The number of entries in the feature name array. */
   HBUINT16     reserved1;      /* Reserved (set to zero). */
   HBUINT32     reserved2;      /* Reserved (set to zero). */
-  UnsizedArrayOf<FeatureName>
-               names         /* The feature name array. */
+  SortedUnsizedArrayOf<FeatureName>
+               namesZ;         /* The feature name array. */
   public:
   DEFINE_SIZE_STATIC (24);
 };
diff --git a/src/hb-aat-layout-just-table.hh b/src/hb-aat-layout-just-table.hh
new file mode 100644 (file)
index 0000000..d53f8f1
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_LAYOUT_JUST_TABLE_HH
+#define HB_AAT_LAYOUT_JUST_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+
+#include "hb-aat-layout-morx-table.hh"
+
+/*
+ * just -- Justification
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html
+ */
+#define HB_AAT_TAG_just HB_TAG('j','u','s','t')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct ActionSubrecordHeader
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  HBUINT16     actionClass;    /* The JustClass value associated with this
+                                * ActionSubrecord. */
+  HBUINT16     actionType;     /* The type of postcompensation action. */
+  HBUINT16     actionLength;   /* Length of this ActionSubrecord record, which
+                                * must be a multiple of 4. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DecompositionAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  ActionSubrecordHeader
+               header;
+  Fixed                lowerLimit;     /* If the distance factor is less than this value,
+                                * then the ligature is decomposed. */
+  Fixed                upperLimit;     /* If the distance factor is greater than this value,
+                                * then the ligature is decomposed. */
+  HBUINT16     order;          /* Numerical order in which this ligature will
+                                * be decomposed; you may want infrequent ligatures
+                                * to decompose before more frequent ones. The ligatures
+                                * on the line of text will decompose in increasing
+                                * value of this field. */
+  ArrayOf<HBUINT16>
+               decomposedglyphs;
+                               /* Number of 16-bit glyph indexes that follow;
+                                * the ligature will be decomposed into these glyphs.
+                                *
+                                * Array of decomposed glyphs. */
+  public:
+  DEFINE_SIZE_ARRAY (18, decomposedglyphs);
+};
+
+struct UnconditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  ActionSubrecordHeader
+               header;
+  GlyphID      addGlyph;       /* Glyph that should be added if the distance factor
+                                * is growing. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ConditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+               header;
+  Fixed        substThreshold; /* Distance growth factor (in ems) at which
+                                * this glyph is replaced and the growth factor
+                                * recalculated. */
+  GlyphID      addGlyph;       /* Glyph to be added as kashida. If this value is
+                                * 0xFFFF, no extra glyph will be added. Note that
+                                * generally when a glyph is added, justification
+                                * will need to be redone. */
+  GlyphID      substGlyph;     /* Glyph to be substituted for this glyph if the
+                                * growth factor equals or exceeds the value of
+                                * substThreshold. */
+  public:
+  DEFINE_SIZE_STATIC (14);
+};
+
+struct DuctileGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+               header;
+  HBUINT32     variationAxis;  /* The 4-byte tag identifying the ductile axis.
+                                * This would normally be 0x64756374 ('duct'),
+                                * but you may use any axis the font contains. */
+  Fixed        minimumLimit;   /* The lowest value for the ductility axis tha
+                                * still yields an acceptable appearance. Normally
+                                * this will be 1.0. */
+  Fixed        noStretchValue; /* This is the default value that corresponds to
+                                * no change in appearance. Normally, this will
+                                * be 1.0. */
+  Fixed        maximumLimit;   /* The highest value for the ductility axis that
+                                * still yields an acceptable appearance. */
+  public:
+  DEFINE_SIZE_STATIC (22);
+};
+
+struct RepeatedAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+               header;
+  HBUINT16     flags;          /* Currently unused; set to 0. */
+  GlyphID      glyph;          /* Glyph that should be added if the distance factor
+                                * is growing. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct ActionSubrecord
+{
+  unsigned int get_length () const { return u.header.actionLength; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.header.actionType)
+    {
+    case 0:  return_trace (u.decompositionAction.sanitize (c));
+    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
+    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
+    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
+    case 4:  return_trace (u.decompositionAction.sanitize (c));
+    case 5:  return_trace (u.decompositionAction.sanitize (c));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union        {
+  ActionSubrecordHeader                header;
+  DecompositionAction          decompositionAction;
+  UnconditionalAddGlyphAction  unconditionalAddGlyphAction;
+  ConditionalAddGlyphAction    conditionalAddGlyphAction;
+  /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */
+  DuctileGlyphAction           ductileGlyphAction;
+  RepeatedAddGlyphAction       repeatedAddGlyphAction;
+  } u;                         /* Data. The format of this data depends on
+                                * the value of the actionType field. */
+  public:
+  DEFINE_SIZE_UNION (6, header);
+};
+
+struct PostcompensationActionChain
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    unsigned int offset = min_size;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset);
+      if (unlikely (!subrecord.sanitize (c))) return_trace (false);
+      offset += subrecord.get_length ();
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT32     count;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct JustWidthDeltaEntry
+{
+  enum Flags
+  {
+    Reserved1          =0xE000,/* Reserved. You should set these bits to zero. */
+    UnlimiteGap                =0x1000,/* The glyph can take unlimited gap. When this
+                                * glyph participates in the justification process,
+                                * it and any other glyphs on the line having this
+                                * bit set absorb all the remaining gap. */
+    Reserved2          =0x0FF0,/* Reserved. You should set these bits to zero. */
+    Priority           =0x000F /* The justification priority of the glyph. */
+  };
+
+  enum Priority
+  {
+    Kashida            = 0,    /* Kashida priority. This is the highest priority
+                                * during justification. */
+    Whitespace         = 1,    /* Whitespace priority. Any whitespace glyphs (as
+                                * identified in the glyph properties table) will
+                                * get this priority. */
+    InterCharacter     = 2,    /* Inter-character priority. Give this to any
+                                * remaining glyphs. */
+    NullPriority       = 3     /* Null priority. You should set this priority for
+                                * glyphs that only participate in justification
+                                * after the above priorities. Normally all glyphs
+                                * have one of the previous three values. If you
+                                * don't want a glyph to participate in justification,
+                                * and you don't want to set its factors to zero,
+                                * you may instead assign it to the null priority. */
+  };
+
+  protected:
+  Fixed                beforeGrowLimit;/* The ratio by which the advance width of the
+                                * glyph is permitted to grow on the left or top side. */
+  Fixed                beforeShrinkLimit;
+                               /* The ratio by which the advance width of the
+                                * glyph is permitted to shrink on the left or top side. */
+  Fixed                afterGrowLimit; /* The ratio by which the advance width of the glyph
+                                * is permitted to shrink on the left or top side. */
+  Fixed                afterShrinkLimit;
+                               /* The ratio by which the advance width of the glyph
+                                * is at most permitted to shrink on the right or
+                                * bottom side. */
+  HBUINT16     growFlags;      /* Flags controlling the grow case. */
+  HBUINT16     shrinkFlags;    /* Flags controlling the shrink case. */
+
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct WidthDeltaPair
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT32     justClass;      /* The justification category associated
+                                * with the wdRecord field. Only 7 bits of
+                                * this field are used. (The other bits are
+                                * used as padding to guarantee longword
+                                * alignment of the following record). */
+  JustWidthDeltaEntry
+               wdRecord;       /* The actual width delta record. */
+
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+  
+typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
+
+struct JustificationCategory
+{
+  typedef void EntryData;
+
+  enum Flags
+  {
+    SetMark            =0x8000,/* If set, make the current glyph the marked
+                                * glyph. */
+    DontAdvance                =0x4000,/* If set, don't advance to the next glyph before
+                                * going to the new state. */
+    MarkCategory       =0x3F80,/* The justification category for the marked
+                                * glyph if nonzero. */
+    CurrentCategory    =0x007F /* The justification category for the current
+                                * glyph if nonzero. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         morphHeader.sanitize (c) &&
+                         stHeader.sanitize (c)));
+  }
+
+  protected:
+  ChainSubtable<ObsoleteTypes>
+               morphHeader;    /* Metamorphosis-style subtable header. */
+  StateTable<ObsoleteTypes, EntryData>
+               stHeader;       /* The justification insertion state table header */
+  public:
+  DEFINE_SIZE_STATIC (30);
+};
+
+struct JustificationHeader
+{
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         justClassTable.sanitize (c, base, base) &&
+                         wdcTable.sanitize (c, base) &&
+                         pcTable.sanitize (c, base) &&
+                         lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  OffsetTo<JustificationCategory>
+               justClassTable; /* Offset to the justification category state table. */
+  OffsetTo<WidthDeltaCluster>
+               wdcTable;       /* Offset from start of justification table to start
+                                * of the subtable containing the width delta factors
+                                * for the glyphs in your font.
+                                *
+                                * The width delta clusters table. */
+  OffsetTo<PostcompensationActionChain>
+               pcTable;        /* Offset from start of justification table to start
+                                * of postcompensation subtable (set to zero if none).
+                                *
+                                * The postcompensation subtable, if present in the font. */
+  Lookup<OffsetTo<WidthDeltaCluster> >
+               lookupTable;    /* Lookup table associating glyphs with width delta
+                                * clusters. See the description of Width Delta Clusters
+                                * table for details on how to interpret the lookup values. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct just
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                         version.major == 1 &&
+                         horizData.sanitize (c, this, this) &&
+                         vertData.sanitize (c, this, this)));
+  }
+
+  protected:
+  FixedVersion<>version;       /* Version of the justification table
+                                * (0x00010000u for version 1.0). */
+  HBUINT16     format;         /* Format of the justification table (set to 0). */
+  OffsetTo<JustificationHeader>
+               horizData;      /* Byte offset from the start of the justification table
+                                * to the header for tables that contain justification
+                                * information for horizontal text.
+                                * If you are not including this information,
+                                * store 0. */
+  OffsetTo<JustificationHeader>
+               vertData;       /* ditto, vertical */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */
index cc03d62..a64c807 100644 (file)
@@ -28,8 +28,7 @@
 #ifndef HB_AAT_LAYOUT_KERX_TABLE_HH
 #define HB_AAT_LAYOUT_KERX_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-aat-layout-common-private.hh"
+#include "hb-kern.hh"
 #include "hb-aat-layout-ankr-table.hh"
 
 /*
@@ -44,12 +43,42 @@ namespace AAT {
 using namespace OT;
 
 
-struct KerxFormat0Records
+static inline int
+kerxTupleKern (int value,
+              unsigned int tupleCount,
+              const void *base,
+              hb_aat_apply_context_t *c)
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  if (likely (!tupleCount || !c)) return value;
+
+  unsigned int offset = value;
+  const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
+  if (unlikely (!c->sanitizer.check_array (pv, tupleCount))) return 0;
+  return *pv;
+}
+
+
+struct hb_glyph_pair_t
+{
+  hb_codepoint_t left;
+  hb_codepoint_t right;
+};
+
+struct KernPair
+{
+  int get_kerning () const { return value; }
+
+  int cmp (const hb_glyph_pair_t &o) const
+  {
+    int ret = left.cmp (o.left);
+    if (ret) return ret;
+    return right.cmp (o.right);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
+    return_trace (c->check_struct (this));
   }
 
   protected:
@@ -60,286 +89,912 @@ struct KerxFormat0Records
   DEFINE_SIZE_STATIC (6);
 };
 
+template <typename KernSubTableHeader>
 struct KerxSubTableFormat0
 {
-  // TODO(ebraminio) Enable when we got suitable BinSearchArrayOf
-  // inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-  // {
-  //   hb_glyph_pair_t pair = {left, right};
-  //   int i = pairs.bsearch (pair);
-  //   if (i == -1)
-  //     return 0;
-  //   return pairs[i].get_kerning ();
-  // }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                  hb_aat_apply_context_t *c = nullptr) const
+  {
+    hb_glyph_pair_t pair = {left, right};
+    int v = pairs.bsearch (pair).get_kerning ();
+    return kerxTupleKern (v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat0 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat0 &table_,
+                  hb_aat_apply_context_t *c_) :
+                    table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         recordsZ.sanitize (c, nPairs)));
+    return_trace (likely (pairs.sanitize (c)));
   }
 
   protected:
-  // TODO(ebraminio): A custom version of "BinSearchArrayOf<KerxPair> pairs;" is
-  // needed here to use HBUINT32 instead
-  HBUINT32     nPairs;         /* The number of kerning pairs in this subtable */
-  HBUINT32     searchRange;    /* The largest power of two less than or equal to the value of nPairs,
-                                * multiplied by the size in bytes of an entry in the subtable. */
-  HBUINT32     entrySelector;  /* This is calculated as log2 of the largest power of two less
-                                * than or equal to the value of nPairs. */
-  HBUINT32     rangeShift;     /* The value of nPairs minus the largest power of two less than or equal to nPairs. */
-  UnsizedArrayOf<KerxFormat0Records>
-               recordsZ;       /* VAR=nPairs */
+  KernSubTableHeader   header;
+  BinSearchArrayOf<KernPair, typename KernSubTableHeader::Types::HBUINT>
+                       pairs;  /* Sorted kern records. */
   public:
-  DEFINE_SIZE_ARRAY (16, recordsZ);
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 16, pairs);
 };
 
-struct KerxSubTableFormat1
+
+template <bool extended>
+struct Format1Entry;
+
+template <>
+struct Format1Entry<true>
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum Flags
   {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         stateHeader.sanitize (c)));
-  }
+    Push               = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance                = 0x4000,       /* If set, don't advance to the next glyph
+                                        * before going to the new state. */
+    Reset              = 0x2000,       /* If set, reset the kerning data (clear the stack) */
+    Reserved           = 0x1FFF,       /* Not used; set to 0. */
+  };
+
+  struct EntryData
+  {
+    HBUINT16   kernActionIndex;/* Index into the kerning value array. If
+                                * this index is 0xFFFF, then no kerning
+                                * is to be performed. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex != 0xFFFF; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex; }
+};
+template <>
+struct Format1Entry<false>
+{
+  enum Flags
+  {
+    Push               = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance                = 0x4000,       /* If set, don't advance to the next glyph
+                                        * before going to the new state. */
+    Offset             = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                        * value table for the glyphs on the kerning stack. */
 
-  protected:
-  StateTable<HBUINT16>         stateHeader;
-  LOffsetTo<ArrayOf<HBUINT16> >        valueTable;
-  public:
-  DEFINE_SIZE_STATIC (20);
+    Reset              = 0x0000,       /* Not supported? */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
 };
 
-// TODO(ebraminio): Maybe this can be replaced with Lookup<HBUINT16>?
-struct KerxClassTable
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat1
 {
-  inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef Format1Entry<Types::extended> Format1EntryT;
+  typedef typename Format1EntryT::EntryData EntryData;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum
+    {
+      DontAdvance      = Format1EntryT::DontAdvance,
+    };
+
+    driver_context_t (const KerxSubTableFormat1 *table_,
+                     hb_aat_apply_context_t *c_) :
+       c (c_),
+       table (table_),
+       /* Apparently the offset kernAction is from the beginning of the state-machine,
+        * similar to offsets in morx table, NOT from beginning of this table, like
+        * other subtables in kerx.  Discovered via testing. */
+       kernAction (&table->machine + table->kernAction),
+       depth (0),
+       crossStream (table->header.coverage & table->header.CrossStream) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                       const Entry<EntryData> &entry)
+    {
+      return Format1EntryT::performAction (entry);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      if (flags & Format1EntryT::Reset)
+       depth = 0;
+
+      if (flags & Format1EntryT::Push)
+      {
+       if (likely (depth < ARRAY_LENGTH (stack)))
+         stack[depth++] = buffer->idx;
+       else
+         depth = 0; /* Probably not what CoreText does, but better? */
+      }
+
+      if (Format1EntryT::performAction (entry) && depth)
+      {
+       unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
+
+       unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
+       kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
+       const FWORD *actions = &kernAction[kern_idx];
+       if (!c->sanitizer.check_array (actions, depth, tuple_count))
+       {
+         depth = 0;
+         return;
+       }
+
+       hb_mask_t kern_mask = c->plan->kern_mask;
+
+       /* From Apple 'kern' spec:
+        * "Each pops one glyph from the kerning stack and applies the kerning value to it.
+        * The end of the list is marked by an odd value... */
+       bool last = false;
+       while (!last && depth)
+       {
+         unsigned int idx = stack[--depth];
+         int v = *actions;
+         actions += tuple_count;
+         if (idx >= buffer->len) continue;
+
+         /* "The end of the list is marked by an odd value..." */
+         last = v & 1;
+         v &= ~1;
+
+         hb_glyph_position_t &o = buffer->pos[idx];
+
+         /* Testing shows that CoreText only applies kern (cross-stream or not)
+          * if none has been applied by previous subtables.  That is, it does
+          * NOT seem to accumulate as otherwise implied by specs. */
+
+         /* The following flag is undocumented in the spec, but described
+          * in the 'kern' table example. */
+         if (v == -0x8000)
+         {
+           o.attach_type() = ATTACH_TYPE_NONE;
+           o.attach_chain() = 0;
+           o.x_offset = o.y_offset = 0;
+         }
+         else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+         {
+           if (crossStream)
+           {
+             if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
+             {
+               o.y_offset = c->font->em_scale_y (v);
+               buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+             }
+           }
+           else if (buffer->info[idx].mask & kern_mask)
+           {
+             if (!buffer->pos[idx].x_offset)
+             {
+               buffer->pos[idx].x_advance += c->font->em_scale_x (v);
+               buffer->pos[idx].x_offset += c->font->em_scale_x (v);
+             }
+           }
+         }
+         else
+         {
+           if (crossStream)
+           {
+             /* CoreText doesn't do crossStream kerning in vertical.  We do. */
+             if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
+             {
+               o.x_offset = c->font->em_scale_x (v);
+               buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+             }
+           }
+           else if (buffer->info[idx].mask & kern_mask)
+           {
+             if (!buffer->pos[idx].y_offset)
+             {
+               buffer->pos[idx].y_advance += c->font->em_scale_y (v);
+               buffer->pos[idx].y_offset += c->font->em_scale_y (v);
+             }
+           }
+         }
+       }
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    const KerxSubTableFormat1 *table;
+    const UnsizedArrayOf<FWORD> &kernAction;
+    unsigned int stack[8];
+    unsigned int depth;
+    bool crossStream;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning &&
+       !(header.coverage & header.CrossStream))
+      return false;
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (firstGlyph.sanitize (c) &&
-                         classes.sanitize (c)));
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (likely (c->check_struct (this) &&
+                         machine.sanitize (c)));
   }
 
   protected:
-  HBUINT16             firstGlyph;     /* First glyph in class range. */
-  ArrayOf<HBUINT16>    classes;        /* Glyph classes. */
+  KernSubTableHeader                           header;
+  StateTable<Types, EntryData>                 machine;
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>    kernAction;
   public:
-  DEFINE_SIZE_ARRAY (4, classes);
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
 };
 
+template <typename KernSubTableHeader>
 struct KerxSubTableFormat2
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  {
-    unsigned int l = (this+leftClassTable).get_class (left);
-    unsigned int r = (this+leftClassTable).get_class (left);
-    unsigned int offset = l * rowWidth + r * sizeof (FWORD);
-    const FWORD *arr = &(this+array);
-    if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
-      return 0;
-    const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
-    if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
-      return 0;
-    return *v;
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                  hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    unsigned int l = (this+leftClassTable).get_class (left, num_glyphs, 0);
+    unsigned int r = (this+rightClassTable).get_class (right, num_glyphs, 0);
+
+    const UnsizedArrayOf<FWORD> &arrayZ = this+array;
+    unsigned int kern_idx = l + r;
+    kern_idx = Types::offsetToIndex (kern_idx, this, &arrayZ);
+    const FWORD *v = &arrayZ[kern_idx];
+    if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+
+    return kerxTupleKern (*v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  struct accelerator_t
+  {
+    const KerxSubTableFormat2 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat2 &table_,
+                  hb_aat_apply_context_t *c_) :
+                    table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                         rowWidth.sanitize (c) &&
                          leftClassTable.sanitize (c, this) &&
                          rightClassTable.sanitize (c, this) &&
-                         array.sanitize (c, this)));
+                         c->check_range (this, array)));
   }
 
   protected:
-  HBUINT32     rowWidth;       /* The width, in bytes, of a row in the table. */
-  LOffsetTo<KerxClassTable>
-               leftClassTable; /* Offset from beginning of this subtable to
-                                * left-hand class table. */
-  LOffsetTo<KerxClassTable>
-               rightClassTable;/* Offset from beginning of this subtable to
-                                * right-hand class table. */
-  LOffsetTo<FWORD>
-               array;          /* Offset from beginning of this subtable to
-                                * the start of the kerning array. */
+  KernSubTableHeader   header;
+  HBUINT               rowWidth;       /* The width, in bytes, of a row in the table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                       leftClassTable; /* Offset from beginning of this subtable to
+                                        * left-hand class table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                       rightClassTable;/* Offset from beginning of this subtable to
+                                        * right-hand class table. */
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>
+                        array;         /* Offset from beginning of this subtable to
+                                        * the start of the kerning array. */
   public:
-  DEFINE_SIZE_STATIC (16);
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 4 * sizeof (HBUINT));
 };
 
+template <typename KernSubTableHeader>
 struct KerxSubTableFormat4
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  typedef ExtendedTypes Types;
+
+  struct EntryData
+  {
+    HBUINT16   ankrActionIndex;/* Either 0xFFFF (for no action) or the index of
+                                * the action to perform. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      Mark             = 0x8000,       /* If set, remember this glyph as the marked glyph. */
+      DontAdvance      = 0x4000,       /* If set, don't advance to the next glyph before
+                                        * going to the new state. */
+      Reserved         = 0x3FFF,       /* Not used; set to 0. */
+    };
+
+    enum SubTableFlags
+    {
+      ActionType       = 0xC0000000,   /* A two-bit field containing the action type. */
+      Unused           = 0x3F000000,   /* Unused - must be zero. */
+      Offset           = 0x00FFFFFF,   /* Masks the offset in bytes from the beginning
+                                        * of the subtable to the beginning of the control
+                                        * point table. */
+    };
+
+    driver_context_t (const KerxSubTableFormat4 *table,
+                            hb_aat_apply_context_t *c_) :
+       c (c_),
+       action_type ((table->flags & ActionType) >> 30),
+       ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
+       mark_set (false),
+       mark (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                       const Entry<EntryData> &entry)
+    {
+      return entry.data.ankrActionIndex != 0xFFFF;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
+      {
+       hb_glyph_position_t &o = buffer->cur_pos();
+       switch (action_type)
+       {
+         case 0: /* Control Point Actions.*/
+         {
+           /* indexed into glyph outline. */
+           const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+           if (!c->sanitizer.check_array (data, 2)) return;
+           HB_UNUSED unsigned int markControlPoint = *data++;
+           HB_UNUSED unsigned int currControlPoint = *data++;
+           hb_position_t markX = 0;
+           hb_position_t markY = 0;
+           hb_position_t currX = 0;
+           hb_position_t currY = 0;
+           if (!c->font->get_glyph_contour_point_for_origin (c->buffer->info[mark].codepoint,
+                                                             markControlPoint,
+                                                             HB_DIRECTION_LTR /*XXX*/,
+                                                             &markX, &markY) ||
+               !c->font->get_glyph_contour_point_for_origin (c->buffer->cur ().codepoint,
+                                                             currControlPoint,
+                                                             HB_DIRECTION_LTR /*XXX*/,
+                                                             &currX, &currY))
+             return;
+
+           o.x_offset = markX - currX;
+           o.y_offset = markY - currY;
+         }
+         break;
+
+         case 1: /* Anchor Point Actions. */
+         {
+          /* Indexed into 'ankr' table. */
+           const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+           if (!c->sanitizer.check_array (data, 2)) return;
+           unsigned int markAnchorPoint = *data++;
+           unsigned int currAnchorPoint = *data++;
+           const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
+                                                                 markAnchorPoint,
+                                                                 c->sanitizer.get_num_glyphs ());
+           const Anchor &currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint,
+                                                                 currAnchorPoint,
+                                                                 c->sanitizer.get_num_glyphs ());
+
+           o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate);
+           o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate);
+         }
+         break;
+
+         case 2: /* Control Point Coordinate Actions. */
+         {
+           const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
+           if (!c->sanitizer.check_array (data, 4)) return;
+           int markX = *data++;
+           int markY = *data++;
+           int currX = *data++;
+           int currY = *data++;
+
+           o.x_offset = c->font->em_scale_x (markX) - c->font->em_scale_x (currX);
+           o.y_offset = c->font->em_scale_y (markY) - c->font->em_scale_y (currY);
+         }
+         break;
+       }
+       o.attach_type() = ATTACH_TYPE_MARK;
+       o.attach_chain() = (int) mark - (int) buffer->idx;
+       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+      }
+
+      if (entry.flags & Mark)
+      {
+       mark_set = true;
+       mark = buffer->idx;
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int action_type;
+    const HBUINT16 *ankrData;
+    bool mark_set;
+    unsigned int mark;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
     return_trace (likely (c->check_struct (this) &&
-                         rowWidth.sanitize (c) &&
-                         leftClassTable.sanitize (c, this) &&
-                         rightClassTable.sanitize (c, this) &&
-                         array.sanitize (c, this)));
+                         machine.sanitize (c)));
   }
 
   protected:
-  HBUINT32     rowWidth;       /* The width, in bytes, of a row in the table. */
-  LOffsetTo<KerxClassTable>
-               leftClassTable; /* Offset from beginning of this subtable to
-                                * left-hand class table. */
-  LOffsetTo<KerxClassTable>
-               rightClassTable;/* Offset from beginning of this subtable to
-                                * right-hand class table. */
-  LOffsetTo<FWORD>
-               array;          /* Offset from beginning of this subtable to
-                                * the start of the kerning array. */
+  KernSubTableHeader           header;
+  StateTable<Types, EntryData> machine;
+  HBUINT32                     flags;
   public:
-  DEFINE_SIZE_STATIC (16);
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
 };
 
+template <typename KernSubTableHeader>
 struct KerxSubTableFormat6
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum Flags
+  {
+    ValuesAreLong      = 0x00000001,
+  };
+
+  bool is_long () const { return flags & ValuesAreLong; }
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                         hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    if (is_long ())
+    {
+      const typename U::Long &t = u.l;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      if (unlikely (offset < l)) return 0; /* Addition overflow. */
+      if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
+      const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+    else
+    {
+      const typename U::Short &t = u.s;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                         rowIndexTable.sanitize (c, this) &&
-                         columnIndexTable.sanitize (c, this) &&
-                         kerningArray.sanitize (c, this) &&
-                         kerningVector.sanitize (c, this)));
+                         (is_long () ?
+                          (
+                            u.l.rowIndexTable.sanitize (c, this) &&
+                            u.l.columnIndexTable.sanitize (c, this) &&
+                            c->check_range (this, u.l.array)
+                          ) : (
+                            u.s.rowIndexTable.sanitize (c, this) &&
+                            u.s.columnIndexTable.sanitize (c, this) &&
+                            c->check_range (this, u.s.array)
+                          )) &&
+                         (header.tuple_count () == 0 ||
+                          c->check_range (this, vector))));
   }
 
+  struct accelerator_t
+  {
+    const KerxSubTableFormat6 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat6 &table_,
+                  hb_aat_apply_context_t *c_) :
+                    table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
   protected:
-  HBUINT32     flags;
-  HBUINT16     rowCount;
-  HBUINT16     columnCount;
-  LOffsetTo<Lookup<HBUINT16> > rowIndexTable;
-  LOffsetTo<Lookup<HBUINT16> > columnIndexTable;
-  LOffsetTo<Lookup<HBUINT16> > kerningArray;
-  LOffsetTo<Lookup<HBUINT16> > kerningVector;
+  KernSubTableHeader           header;
+  HBUINT32                     flags;
+  HBUINT16                     rowCount;
+  HBUINT16                     columnCount;
+  union U
+  {
+    struct Long
+    {
+      LNNOffsetTo<Lookup<HBUINT32> >           rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT32> >           columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD32> >    array;
+    } l;
+    struct Short
+    {
+      LNNOffsetTo<Lookup<HBUINT16> >           rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT16> >           columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD> >      array;
+    } s;
+  } u;
+  LNNOffsetTo<UnsizedArrayOf<FWORD> >  vector;
   public:
-  DEFINE_SIZE_STATIC (24);
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
 };
 
-enum coverage_flags_t
+
+struct KerxSubTableHeader
 {
-  COVERAGE_VERTICAL_FLAG       = 0x80u,
-  COVERAGE_CROSSSTREAM_FLAG    = 0x40u,
-  COVERAGE_VARIATION_FLAG      = 0x20u,
-  COVERAGE_PROCESS_DIRECTION   = 0x10u,
+  typedef ExtendedTypes Types;
+
+  unsigned int tuple_count () const { return tupleCount; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
+
+  enum Coverage
+  {
+    Vertical   = 0x80000000u,  /* Set if table has vertical kerning values. */
+    CrossStream        = 0x40000000u,  /* Set if table has cross-stream kerning values. */
+    Variation  = 0x20000000u,  /* Set if table has variation kerning values. */
+    Backwards  = 0x10000000u,  /* If clear, process the glyphs forwards, that
+                                * is, from first to last in the glyph stream.
+                                * If we, process them from last to first.
+                                * This flag only applies to state-table based
+                                * 'kerx' subtables (types 1 and 4). */
+    Reserved   = 0x0FFFFF00u,  /* Reserved, set to zero. */
+    SubtableType= 0x000000FFu, /* Subtable type. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  public:
+  HBUINT32     length;
+  HBUINT32     coverage;
+  HBUINT32     tupleCount;
+  public:
+  DEFINE_SIZE_STATIC (12);
 };
 
-struct KerxTable
+struct KerxSubTable
 {
-  inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const
+  friend struct kerx;
+
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
   {
-    TRACE_APPLY (this);
-    /* TODO */
-    return_trace (false);
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:    return_trace (c->dispatch (u.format0));
+    case 1:    return_trace (c->dispatch (u.format1));
+    case 2:    return_trace (c->dispatch (u.format2));
+    case 4:    return_trace (c->dispatch (u.format4));
+    case 6:    return_trace (c->dispatch (u.format6));
+    default:   return_trace (c->default_return_value ());
+    }
   }
 
-  inline unsigned int get_size (void) const { return length; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
+    if (!u.header.sanitize (c) ||
+       u.header.length <= u.header.static_size ||
+       !c->check_range (this, u.header.length))
       return_trace (false);
 
-    switch (format) {
-    case 0: return u.format0.sanitize (c);
-    case 1: return u.format1.sanitize (c);
-    case 2: return u.format2.sanitize (c);
-    case 4: return u.format4.sanitize (c);
-    case 6: return u.format6.sanitize (c);
-    default:return_trace (false);
-    }
+    return_trace (dispatch (c));
   }
 
-protected:
-  HBUINT32     length;
-  HBUINT8      coverage;
-  HBUINT16     unused;
-  HBUINT8      format;
-  HBUINT32     tupleIndex;
+  public:
   union {
-  KerxSubTableFormat0  format0;
-  KerxSubTableFormat1  format1;
-  KerxSubTableFormat2  format2;
-  KerxSubTableFormat4  format4;
-  KerxSubTableFormat6  format6;
+  KerxSubTableHeader                           header;
+  KerxSubTableFormat0<KerxSubTableHeader>      format0;
+  KerxSubTableFormat1<KerxSubTableHeader>      format1;
+  KerxSubTableFormat2<KerxSubTableHeader>      format2;
+  KerxSubTableFormat4<KerxSubTableHeader>      format4;
+  KerxSubTableFormat6<KerxSubTableHeader>      format6;
   } u;
-public:
+  public:
   DEFINE_SIZE_MIN (12);
 };
 
-struct SubtableGlyphCoverageArray
+
+/*
+ * The 'kerx' Table
+ */
+
+template <typename T>
+struct KerxTable
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const T* thiz () const { return static_cast<const T *> (this); }
+
+  bool has_state_machine () const
   {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->get_type () == 1)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
   }
 
-  protected:
-  HBUINT32     length;
-  HBUINT32     coverage;
-  HBUINT32     tupleCount;
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
+  bool has_cross_stream () const
+  {
+    typedef typename T::SubTable SubTable;
 
-struct kerx
-{
-  static const hb_tag_t tableTag = HB_AAT_TAG_kerx;
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->u.header.coverage & st->u.header.CrossStream)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
+  }
 
-  inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    TRACE_APPLY (this);
-    const KerxTable &table = StructAfter<KerxTable> (*this);
-    return_trace (table.apply (c, ankr));
+    typedef typename T::SubTable SubTable;
+
+    int v = 0;
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if ((st->u.header.coverage & (st->u.header.Variation | st->u.header.CrossStream)) ||
+         !st->u.header.is_horizontal ())
+        continue;
+      v += st->get_kerning (left, right);
+      st = &StructAfter<SubTable> (*st);
+    }
+    return v;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool apply (AAT::hb_aat_apply_context_t *c) const
   {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this))))
-     return_trace (false);
+    typedef typename T::SubTable SubTable;
+
+    bool ret = false;
+    bool seenCrossStream = false;
+    c->set_lookup_index (0);
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      bool reverse;
+
+      if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
+        goto skip;
+
+      if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
+       goto skip;
+
+      reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
+               HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
+      if (!c->buffer->message (c->font, "start %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index))
+       goto skip;
+
+      if (!seenCrossStream &&
+         (st->u.header.coverage & st->u.header.CrossStream))
+      {
+        /* Attach all glyphs into a chain. */
+        seenCrossStream = true;
+       hb_glyph_position_t *pos = c->buffer->pos;
+       unsigned int count = c->buffer->len;
+       for (unsigned int i = 0; i < count; i++)
+       {
+         pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+         pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
+         /* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
+          * since there needs to be a non-zero attachment for post-positioning to
+          * be needed. */
+       }
+      }
+
+      if (reverse)
+       c->buffer->reverse ();
+
+      {
+       /* See comment in sanitize() for conditional here. */
+       hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
+       ret |= st->dispatch (c);
+      }
+
+      if (reverse)
+       c->buffer->reverse ();
+
+      (void) c->buffer->message (c->font, "end %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index);
+
+    skip:
+      st = &StructAfter<SubTable> (*st);
+      c->set_lookup_index (c->lookup_index + 1);
+    }
 
-    /* TODO: Something like `morx`s ChainSubtable should be done here instead */
-    const KerxTable *table = &StructAfter<KerxTable> (*this);
-    if (unlikely (!(table->sanitize (c))))
+    return ret;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!thiz()->version.sanitize (c) ||
+                 (unsigned) thiz()->version < (unsigned) T::minVersion ||
+                 !thiz()->tableCount.sanitize (c)))
       return_trace (false);
 
-    for (unsigned int i = 0; i < nTables - 1; ++i)
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
     {
-      table = &StructAfter<KerxTable> (*table);
-      if (unlikely (!(table->sanitize (c))))
-        return_trace (false);
+      if (unlikely (!st->u.header.sanitize (c)))
+       return_trace (false);
+      /* OpenType kern table has 2-byte subtable lengths.  That's limiting.
+       * MS implementation also only supports one subtable, of format 0,
+       * anyway.  Certain versions of some fonts, like Calibry, contain
+       * kern subtable that exceeds 64kb.  Looks like, the subtable length
+       * is simply ignored.  Which makes sense.  It's only needed if you
+       * have multiple subtables.  To handle such fonts, we just ignore
+       * the length for the last subtable. */
+      hb_sanitize_with_object_t with (c, i < count - 1 ? st : (const SubTable *) nullptr);
+
+      if (unlikely (!st->sanitize (c)))
+       return_trace (false);
+
+      st = &StructAfter<SubTable> (*st);
     }
 
-    // If version is less than 3, we are done here; otherwise better to check footer also
-    if (version < 3)
-      return_trace (true);
-
-    // TODO: Investigate why this just work on some fonts no matter of version
-    // const SubtableGlyphCoverageArray &footer =
-    //   StructAfter<SubtableGlyphCoverageArray> (*table);
-    // return_trace (footer.sanitize (c));
-
     return_trace (true);
   }
+};
+
+struct kerx : KerxTable<kerx>
+{
+  friend struct KerxTable<kerx>;
+
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_kerx;
+  static constexpr unsigned minVersion = 2u;
+
+  typedef KerxSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KerxSubTable SubTable;
+
+  bool has_data () const { return version; }
 
   protected:
-  HBUINT16             version;
-  HBUINT16             padding;
-  HBUINT32             nTables;
-/*KerxTable tablesZ[VAR]; XXX ArrayOf??? */
-/*SubtableGlyphCoverageArray coverage_array;*/
+  HBUINT16     version;        /* The version number of the extended kerning table
+                                * (currently 2, 3, or 4). */
+  HBUINT16     unused;         /* Set to 0. */
+  HBUINT32     tableCount;     /* The number of subtables included in the extended kerning
+                                * table. */
+  SubTable     firstSubTable;  /* Subtables. */
+/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
+
   public:
-  DEFINE_SIZE_STATIC (8);
+  DEFINE_SIZE_MIN (8);
 };
 
+
 } /* namespace AAT */
 
 
diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh
new file mode 100644 (file)
index 0000000..4be799f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+#ifndef HB_AAT_LAYOUT_LCAR_TABLE_HH
+#define HB_AAT_LAYOUT_LCAR_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+
+/*
+ * lcar -- Ligature caret
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6lcar.html
+ */
+#define HB_AAT_TAG_lcar HB_TAG('l','c','a','r')
+
+
+namespace AAT {
+
+typedef ArrayOf<HBINT16> LigCaretClassEntry;
+
+struct lcar
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
+
+  unsigned int get_lig_carets (hb_font_t      *font,
+                              hb_direction_t  direction,
+                              hb_codepoint_t  glyph,
+                              unsigned int    start_offset,
+                              unsigned int   *caret_count /* IN/OUT */,
+                              hb_position_t  *caret_array /* OUT */) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
+                                                                        font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; ++i)
+       switch (format)
+       {
+       case 0: caret_array[i] = font->em_scale_dir (arr[i], direction); break;
+       case 1:
+         hb_position_t x, y;
+         font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
+         caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+         break;
+       }
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         version.major == 1 &&
+                         lookup.sanitize (c, this)));
+  }
+
+  protected:
+  FixedVersion<>version;       /* Version number of the ligature caret table */
+  HBUINT16     format;         /* Format of the ligature caret table. */
+  Lookup<OffsetTo<LigCaretClassEntry> >
+               lookup;         /* data Lookup table associating glyphs */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+#endif /* HB_AAT_LAYOUT_LCAR_TABLE_HH */
index f258424..4a1d959 100644 (file)
 #ifndef HB_AAT_LAYOUT_MORX_TABLE_HH
 #define HB_AAT_LAYOUT_MORX_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-aat-layout-common-private.hh"
-#include "hb-ot-layout-common-private.hh"
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-aat-map.hh"
 
 /*
  * morx -- Extended Glyph Metamorphosis
  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
  */
 #define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
 
 
 namespace AAT {
 
 using namespace OT;
 
-
+template <typename Types>
 struct RearrangementSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   typedef void EntryData;
 
   struct driver_context_t
   {
-    static const bool in_place = true;
-    enum Flags {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
       MarkFirst                = 0x8000,       /* If set, make the current glyph the first
                                         * glyph to be rearranged. */
       DontAdvance      = 0x4000,       /* If set, don't advance to the next glyph
@@ -63,20 +69,20 @@ struct RearrangementSubtable
       Verb             = 0x000F,       /* The type of rearrangement specified. */
     };
 
-    inline driver_context_t (const RearrangementSubtable *table) :
+    driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
        ret (false),
        start (0), end (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver,
-                              const Entry<EntryData> *entry)
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                       const Entry<EntryData> &entry)
     {
-      return (entry->flags & Verb) && start < end;
+      return (entry.flags & Verb) && start < end;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
-                           const Entry<EntryData> *entry)
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
     {
       hb_buffer_t *buffer = driver->buffer;
-      unsigned int flags = entry->flags;
+      unsigned int flags = entry.flags;
 
       if (flags & MarkFirst)
        start = buffer->idx;
@@ -146,8 +152,6 @@ struct RearrangementSubtable
          }
        }
       }
-
-      return true;
     }
 
     public:
@@ -157,32 +161,35 @@ struct RearrangementSubtable
     unsigned int end;
   };
 
-  inline bool apply (hb_aat_apply_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
     driver_context_t dc (this);
 
-    StateTableDriver<void> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (machine.sanitize (c));
   }
 
   protected:
-  StateTable<EntryData>        machine;
+  StateTable<Types, EntryData> machine;
   public:
   DEFINE_SIZE_STATIC (16);
 };
 
+template <typename Types>
 struct ContextualSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   struct EntryData
   {
     HBUINT16   markIndex;      /* Index of the substitution table for the
@@ -195,101 +202,133 @@ struct ContextualSubtable
 
   struct driver_context_t
   {
-    static const bool in_place = true;
-    enum Flags {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
       SetMark          = 0x8000,       /* If set, make the current glyph the marked glyph. */
       DontAdvance      = 0x4000,       /* If set, don't advance to the next glyph before
                                         * going to the new state. */
       Reserved         = 0x3FFF,       /* These bits are reserved and should be set to 0. */
     };
 
-    inline driver_context_t (const ContextualSubtable *table) :
+    driver_context_t (const ContextualSubtable *table_,
+                            hb_aat_apply_context_t *c_) :
        ret (false),
+       c (c_),
        mark_set (false),
        mark (0),
+       table (table_),
        subs (table+table->substitutionTables) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver,
-                              const Entry<EntryData> *entry)
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver,
+                       const Entry<EntryData> &entry)
     {
       hb_buffer_t *buffer = driver->buffer;
 
       if (buffer->idx == buffer->len && !mark_set)
         return false;
 
-      return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
+      return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
-                           const Entry<EntryData> *entry)
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
     {
       hb_buffer_t *buffer = driver->buffer;
 
       /* Looks like CoreText applies neither mark nor current substitution for
        * end-of-text if mark was not explicitly set. */
       if (buffer->idx == buffer->len && !mark_set)
-        return true;
+        return;
+
+      const GlyphID *replacement;
 
-      if (entry->data.markIndex != 0xFFFF)
+      replacement = nullptr;
+      if (Types::extended)
       {
-       const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
-       hb_glyph_info_t *info = buffer->info;
-       const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs);
-       if (replacement)
+       if (entry.data.markIndex != 0xFFFF)
        {
-         buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
-         info[mark].codepoint = *replacement;
-         ret = true;
+         const Lookup<GlyphID> &lookup = subs[entry.data.markIndex];
+         replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
        }
       }
-      if (entry->data.currentIndex != 0xFFFF)
+      else
+      {
+       unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
+       const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+       replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+       if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+         replacement = nullptr;
+      }
+      if (replacement)
       {
-        unsigned int idx = MIN (buffer->idx, buffer->len - 1);
-       const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
-       hb_glyph_info_t *info = buffer->info;
-       const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs);
-       if (replacement)
+       buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
+       buffer->info[mark].codepoint = *replacement;
+       ret = true;
+      }
+
+      replacement = nullptr;
+      unsigned int idx = MIN (buffer->idx, buffer->len - 1);
+      if (Types::extended)
+      {
+       if (entry.data.currentIndex != 0xFFFF)
        {
-         info[idx].codepoint = *replacement;
-         ret = true;
+         const Lookup<GlyphID> &lookup = subs[entry.data.currentIndex];
+         replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
        }
       }
+      else
+      {
+       unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
+       const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+       replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+       if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+         replacement = nullptr;
+      }
+      if (replacement)
+      {
+       buffer->info[idx].codepoint = *replacement;
+       ret = true;
+      }
 
-      if (entry->flags & SetMark)
+      if (entry.flags & SetMark)
       {
        mark_set = true;
        mark = buffer->idx;
       }
-
-      return true;
     }
 
     public:
     bool ret;
     private:
+    hb_aat_apply_context_t *c;
     bool mark_set;
     unsigned int mark;
-    const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
+    const ContextualSubtable *table;
+    const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs;
   };
 
-  inline bool apply (hb_aat_apply_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
-    driver_context_t dc (this);
+    driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
     unsigned int num_entries = 0;
     if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
 
+    if (!Types::extended)
+      return_trace (substitutionTables.sanitize (c, this, 0));
+
     unsigned int num_lookups = 0;
 
     const Entry<EntryData> *entries = machine.get_entries ();
@@ -307,16 +346,32 @@ struct ContextualSubtable
   }
 
   protected:
-  StateTable<EntryData>
+  StateTable<Types, EntryData>
                machine;
-  LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> >
+  NNOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT>
                substitutionTables;
   public:
   DEFINE_SIZE_STATIC (20);
 };
 
-struct LigatureSubtable
+
+template <bool extended>
+struct LigatureEntry;
+
+template <>
+struct LigatureEntry<true>
 {
+  enum Flags
+  {
+    SetComponent       = 0x8000,       /* Push this glyph onto the component stack for
+                                        * eventual processing. */
+    DontAdvance                = 0x4000,       /* Leave the glyph pointer at this glyph for the
+                                          next iteration. */
+    PerformAction      = 0x2000,       /* Use the ligActionIndex to process a ligature
+                                        * group. */
+    Reserved           = 0x1FFF,       /* These bits are reserved and should be set to 0. */
+  };
+
   struct EntryData
   {
     HBUINT16   ligActionIndex; /* Index to the first ligActionTable entry
@@ -326,19 +381,53 @@ struct LigatureSubtable
     DEFINE_SIZE_STATIC (2);
   };
 
-  struct driver_context_t
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & PerformAction; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.ligActionIndex; }
+};
+template <>
+struct LigatureEntry<false>
+{
+  enum Flags
   {
-    static const bool in_place = false;
-    enum Flags {
-      SetComponent     = 0x8000,       /* Push this glyph onto the component stack for
+    SetComponent       = 0x8000,       /* Push this glyph onto the component stack for
                                         * eventual processing. */
-      DontAdvance      = 0x4000,       /* Leave the glyph pointer at this glyph for the
+    DontAdvance                = 0x4000,       /* Leave the glyph pointer at this glyph for the
                                           next iteration. */
-      PerformAction    = 0x2000,       /* Use the ligActionIndex to process a ligature
-                                        * group. */
-      Reserved         = 0x1FFF,       /* These bits are reserved and should be set to 0. */
+    Offset             = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                        * ligature action list. This value must be a
+                                        * multiple of 4. */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+};
+
+
+template <typename Types>
+struct LigatureSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef LigatureEntry<Types::extended> LigatureEntryT;
+  typedef typename LigatureEntryT::EntryData EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum
+    {
+      DontAdvance      = LigatureEntryT::DontAdvance,
     };
-    enum LigActionFlags {
+    enum LigActionFlags
+    {
       LigActionLast    = 0x80000000,   /* This is the last action in the list. This also
                                         * implies storage. */
       LigActionStore   = 0x40000000,   /* Store the ligature at the current cumulated index
@@ -349,96 +438,120 @@ struct LigatureSubtable
                                         * into the component table. */
     };
 
-    inline driver_context_t (const LigatureSubtable *table,
-                            hb_aat_apply_context_t *c_) :
+    driver_context_t (const LigatureSubtable *table_,
+                     hb_aat_apply_context_t *c_) :
        ret (false),
        c (c_),
+       table (table_),
        ligAction (table+table->ligAction),
        component (table+table->component),
        ligature (table+table->ligature),
        match_length (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver,
-                              const Entry<EntryData> *entry)
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                       const Entry<EntryData> &entry)
     {
-      return !!(entry->flags & PerformAction);
+      return LigatureEntryT::performAction (entry);
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
-                           const Entry<EntryData> *entry)
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
     {
       hb_buffer_t *buffer = driver->buffer;
-      unsigned int flags = entry->flags;
 
-      if (flags & SetComponent)
+      DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
+      if (entry.flags & LigatureEntryT::SetComponent)
       {
-        if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
-         return false;
-
        /* Never mark same index twice, in case DontAdvance was used... */
-       if (match_length && match_positions[match_length - 1] == buffer->out_len)
+       if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
          match_length--;
 
-       match_positions[match_length++] = buffer->out_len;
+       match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
+       DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len);
       }
 
-      if (flags & PerformAction)
+      if (LigatureEntryT::performAction (entry))
       {
+       DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length);
        unsigned int end = buffer->out_len;
-       unsigned int action_idx = entry->data.ligActionIndex;
-       unsigned int action;
+
+       if (unlikely (!match_length))
+         return;
+
+       if (buffer->idx >= buffer->len)
+         return; /* TODO Work on previous instead? */
+
+       unsigned int cursor = match_length;
+
+       unsigned int action_idx = LigatureEntryT::ligActionIndex (entry);
+       action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ);
+       const HBUINT32 *actionData = &ligAction[action_idx];
+
        unsigned int ligature_idx = 0;
+       unsigned int action;
         do
        {
-         if (unlikely (!match_length))
-           return false;
+         if (unlikely (!cursor))
+         {
+           /* Stack underflow.  Clear the stack. */
+           DEBUG_MSG (APPLY, nullptr, "Stack underflow");
+           match_length = 0;
+           break;
+         }
 
-         buffer->move_to (match_positions[--match_length]);
+         DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
+         buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
 
-         const HBUINT32 &actionData = ligAction[action_idx];
-         if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
-         action = actionData;
+         if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
+         action = *actionData;
 
          uint32_t uoffset = action & LigActionOffset;
          if (uoffset & 0x20000000)
-           uoffset += 0xC0000000;
+           uoffset |= 0xC0000000; /* Sign-extend. */
          int32_t offset = (int32_t) uoffset;
          unsigned int component_idx = buffer->cur().codepoint + offset;
-
+         component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
          const HBUINT16 &componentData = component[component_idx];
-         if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
+         if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
          ligature_idx += componentData;
 
+         DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
+                    bool (action & LigActionStore),
+                    bool (action & LigActionLast));
          if (action & (LigActionStore | LigActionLast))
          {
+           ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
            const GlyphID &ligatureData = ligature[ligature_idx];
-           if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
+           if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
            hb_codepoint_t lig = ligatureData;
 
-           match_positions[match_length++] = buffer->out_len;
+           DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
            buffer->replace_glyph (lig);
 
-           //ligature_idx = 0; // XXX Yes or no?
-         }
-         else
-         {
-           buffer->skip_glyph ();
-           end--;
+           unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
+           /* Now go and delete all subsequent components. */
+           while (match_length - 1u > cursor)
+           {
+             DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
+             buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
+             buffer->replace_glyph (DELETED_GLYPH);
+           }
+
+           buffer->move_to (lig_end);
+           buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
          }
-         /* TODO merge_clusters / unsafe_to_break */
 
-         action_idx++;
+         actionData++;
        }
        while (!(action & LigActionLast));
        buffer->move_to (end);
       }
-
-      return true;
     }
 
     public:
     bool ret;
     private:
     hb_aat_apply_context_t *c;
+    const LigatureSubtable *table;
     const UnsizedArrayOf<HBUINT32> &ligAction;
     const UnsizedArrayOf<HBUINT16> &component;
     const UnsizedArrayOf<GlyphID> &ligature;
@@ -446,19 +559,19 @@ struct LigatureSubtable
     unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
   };
 
-  inline bool apply (hb_aat_apply_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     /* The rest of array sanitizations are done at run-time. */
@@ -467,21 +580,22 @@ struct LigatureSubtable
   }
 
   protected:
-  StateTable<EntryData>
+  StateTable<Types, EntryData>
                machine;
-  LOffsetTo<UnsizedArrayOf<HBUINT32> >
+  NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
                ligAction;      /* Offset to the ligature action table. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
+  NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
                component;      /* Offset to the component table. */
-  LOffsetTo<UnsizedArrayOf<GlyphID> >
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
                ligature;       /* Offset to the actual ligature lists. */
   public:
   DEFINE_SIZE_STATIC (28);
 };
 
+template <typename Types>
 struct NoncontextualSubtable
 {
-  inline bool apply (hb_aat_apply_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -503,7 +617,7 @@ struct NoncontextualSubtable
     return_trace (ret);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (substitute.sanitize (c));
@@ -515,27 +629,207 @@ struct NoncontextualSubtable
   DEFINE_SIZE_MIN (2);
 };
 
+template <typename Types>
 struct InsertionSubtable
 {
-  inline bool apply (hb_aat_apply_context_t *c) const
+  typedef typename Types::HBUINT HBUINT;
+
+  struct EntryData
+  {
+    HBUINT16   currentInsertIndex;     /* Zero-based index into the insertion glyph table.
+                                        * The number of glyphs to be inserted is contained
+                                        * in the currentInsertCount field in the flags.
+                                        * A value of 0xFFFF indicates no insertion is to
+                                        * be done. */
+    HBUINT16   markedInsertIndex;      /* Zero-based index into the insertion glyph table.
+                                        * The number of glyphs to be inserted is contained
+                                        * in the markedInsertCount field in the flags.
+                                        * A value of 0xFFFF indicates no insertion is to
+                                        * be done. */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum Flags
+    {
+      SetMark          = 0x8000,       /* If set, mark the current glyph. */
+      DontAdvance      = 0x4000,       /* If set, don't advance to the next glyph before
+                                        * going to the new state.  This does not mean
+                                        * that the glyph pointed to is the same one as
+                                        * before. If you've made insertions immediately
+                                        * downstream of the current glyph, the next glyph
+                                        * processed would in fact be the first one
+                                        * inserted. */
+      CurrentIsKashidaLike= 0x2000,    /* If set, and the currentInsertList is nonzero,
+                                        * then the specified glyph list will be inserted
+                                        * as a kashida-like insertion, either before or
+                                        * after the current glyph (depending on the state
+                                        * of the currentInsertBefore flag). If clear, and
+                                        * the currentInsertList is nonzero, then the
+                                        * specified glyph list will be inserted as a
+                                        * split-vowel-like insertion, either before or
+                                        * after the current glyph (depending on the state
+                                        * of the currentInsertBefore flag). */
+      MarkedIsKashidaLike= 0x1000,     /* If set, and the markedInsertList is nonzero,
+                                        * then the specified glyph list will be inserted
+                                        * as a kashida-like insertion, either before or
+                                        * after the marked glyph (depending on the state
+                                        * of the markedInsertBefore flag). If clear, and
+                                        * the markedInsertList is nonzero, then the
+                                        * specified glyph list will be inserted as a
+                                        * split-vowel-like insertion, either before or
+                                        * after the marked glyph (depending on the state
+                                        * of the markedInsertBefore flag). */
+      CurrentInsertBefore= 0x0800,     /* If set, specifies that insertions are to be made
+                                        * to the left of the current glyph. If clear,
+                                        * they're made to the right of the current glyph. */
+      MarkedInsertBefore= 0x0400,      /* If set, specifies that insertions are to be
+                                        * made to the left of the marked glyph. If clear,
+                                        * they're made to the right of the marked glyph. */
+      CurrentInsertCount= 0x3E0,       /* This 5-bit field is treated as a count of the
+                                        * number of glyphs to insert at the current
+                                        * position. Since zero means no insertions, the
+                                        * largest number of insertions at any given
+                                        * current location is 31 glyphs. */
+      MarkedInsertCount= 0x001F,       /* This 5-bit field is treated as a count of the
+                                        * number of glyphs to insert at the marked
+                                        * position. Since zero means no insertions, the
+                                        * largest number of insertions at any given
+                                        * marked location is 31 glyphs. */
+    };
+
+    driver_context_t (const InsertionSubtable *table,
+                     hb_aat_apply_context_t *c_) :
+       ret (false),
+       c (c_),
+       mark (0),
+       insertionAction (table+table->insertionAction) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                       const Entry<EntryData> &entry)
+    {
+      return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+            (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                    const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      unsigned mark_loc = buffer->out_len;
+
+      if (entry.data.markedInsertIndex != 0xFFFF)
+      {
+       unsigned int count = (flags & MarkedInsertCount);
+       unsigned int start = entry.data.markedInsertIndex;
+       const GlyphID *glyphs = &insertionAction[start];
+       if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+       bool before = flags & MarkedInsertBefore;
+
+       unsigned int end = buffer->out_len;
+       buffer->move_to (mark);
+
+       if (buffer->idx < buffer->len && !before)
+         buffer->copy_glyph ();
+       /* TODO We ignore KashidaLike setting. */
+       for (unsigned int i = 0; i < count; i++)
+         buffer->output_glyph (glyphs[i]);
+       if (buffer->idx < buffer->len && !before)
+         buffer->skip_glyph ();
+
+       buffer->move_to (end + count);
+
+       buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
+      }
+
+      if (flags & SetMark)
+       mark = mark_loc;
+
+      if (entry.data.currentInsertIndex != 0xFFFF)
+      {
+       unsigned int count = (flags & CurrentInsertCount) >> 5;
+       unsigned int start = entry.data.currentInsertIndex;
+       const GlyphID *glyphs = &insertionAction[start];
+       if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+       bool before = flags & CurrentInsertBefore;
+
+       unsigned int end = buffer->out_len;
+
+       if (buffer->idx < buffer->len && !before)
+         buffer->copy_glyph ();
+       /* TODO We ignore KashidaLike setting. */
+       for (unsigned int i = 0; i < count; i++)
+         buffer->output_glyph (glyphs[i]);
+       if (buffer->idx < buffer->len && !before)
+         buffer->skip_glyph ();
+
+       /* Humm. Not sure where to move to.  There's this wording under
+        * DontAdvance flag:
+        *
+        * "If set, don't update the glyph index before going to the new state.
+        * This does not mean that the glyph pointed to is the same one as
+        * before. If you've made insertions immediately downstream of the
+        * current glyph, the next glyph processed would in fact be the first
+        * one inserted."
+        *
+        * This suggests that if DontAdvance is NOT set, we should move to
+        * end+count.  If it *was*, then move to end, such that newly inserted
+        * glyphs are now visible.
+        *
+        * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
+        */
+       buffer->move_to ((flags & DontAdvance) ? end : end + count);
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int mark;
+    const UnsizedArrayOf<GlyphID> &insertionAction;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    /* TODO */
-    return_trace (false);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    /* TODO */
-    return_trace (true);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                 insertionAction);
   }
+
+  protected:
+  StateTable<Types, EntryData>
+               machine;
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
+               insertionAction;        /* Byte offset from stateHeader to the start of
+                                        * the insertion glyph table. */
+  public:
+  DEFINE_SIZE_STATIC (20);
 };
 
 
 struct Feature
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -553,15 +847,35 @@ struct Feature
   DEFINE_SIZE_STATIC (12);
 };
 
-
+template <typename Types>
 struct ChainSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
+  template <typename T>
   friend struct Chain;
 
-  inline unsigned int get_size (void) const { return length; }
-  inline unsigned int get_type (void) const { return coverage & 0xFF; }
+  unsigned int get_size () const     { return length; }
+  unsigned int get_type () const     { return coverage & 0xFF; }
+  unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); }
 
-  enum Type {
+  enum Coverage
+  {
+    Vertical           = 0x80, /* If set, this subtable will only be applied
+                                * to vertical text. If clear, this subtable
+                                * will only be applied to horizontal text. */
+    Backwards          = 0x40, /* If set, this subtable will process glyphs
+                                * in descending order. If clear, it will
+                                * process the glyphs in ascending order. */
+    AllDirections      = 0x20, /* If set, this subtable will be applied to
+                                * both horizontal and vertical text (i.e.
+                                * the state of bit 0x80000000 is ignored). */
+    Logical            = 0x10, /* If set, this subtable will process glyphs
+                                * in logical order (or reverse logical order,
+                                * depending on the value of bit 0x80000000). */
+  };
+  enum Type
+  {
     Rearrangement      = 0,
     Contextual         = 1,
     Ligature           = 2,
@@ -569,13 +883,8 @@ struct ChainSubtable
     Insertion          = 5
   };
 
-  inline void apply (hb_aat_apply_context_t *c) const
-  {
-    dispatch (c);
-  }
-
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
@@ -589,58 +898,147 @@ struct ChainSubtable
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    hb_sanitize_with_object_t with (&c->sanitizer, this);
+    return_trace (dispatch (c));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!length.sanitize (c) ||
-       length < min_size ||
+       length <= min_size ||
        !c->check_range (this, length))
       return_trace (false);
 
+    hb_sanitize_with_object_t with (c, this);
     return_trace (dispatch (c));
   }
 
   protected:
-  HBUINT32     length;         /* Total subtable length, including this header. */
-  HBUINT32     coverage;       /* Coverage flags and subtable type. */
+  HBUINT       length;         /* Total subtable length, including this header. */
+  HBUINT       coverage;       /* Coverage flags and subtable type. */
   HBUINT32     subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
   union {
-  RearrangementSubtable                rearrangement;
-  ContextualSubtable           contextual;
-  LigatureSubtable             ligature;
-  NoncontextualSubtable                noncontextual;
-  InsertionSubtable            insertion;
+  RearrangementSubtable<Types> rearrangement;
+  ContextualSubtable<Types>    contextual;
+  LigatureSubtable<Types>      ligature;
+  NoncontextualSubtable<Types> noncontextual;
+  InsertionSubtable<Types>     insertion;
   } u;
   public:
-  DEFINE_SIZE_MIN (12);
+  DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
 };
 
+template <typename Types>
 struct Chain
 {
-  inline void apply (hb_aat_apply_context_t *c) const
+  typedef typename Types::HBUINT HBUINT;
+
+  hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
   {
-    const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
+    hb_mask_t flags = defaultFlags;
+    {
+      unsigned int count = featureCount;
+      for (unsigned i = 0; i < count; i++)
+      {
+       const Feature &feature = featureZ[i];
+       hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
+       hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
+      retry:
+       const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
+       if (info && info->setting == setting)
+       {
+         flags &= feature.disableFlags;
+         flags |= feature.enableFlags;
+       }
+       else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS)
+       {
+         /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */
+         type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE;
+         setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
+         goto retry;
+       }
+      }
+    }
+    return flags;
+  }
+
+  void apply (hb_aat_apply_context_t *c,
+                    hb_mask_t flags) const
+  {
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
+      bool reverse;
+
+      if (!(subtable->subFeatureFlags & flags))
+        goto skip;
+
+      if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
+         HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
+         bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
+        goto skip;
+
+      /* Buffer contents is always in logical direction.  Determine if
+       * we need to reverse before applying this subtable.  We reverse
+       * back after if we did reverse indeed.
+       *
+       * Quoting the spac:
+       * """
+       * Bits 28 and 30 of the coverage field control the order in which
+       * glyphs are processed when the subtable is run by the layout engine.
+       * Bit 28 is used to indicate if the glyph processing direction is
+       * the same as logical order or layout order. Bit 30 is used to
+       * indicate whether glyphs are processed forwards or backwards within
+       * that order.
+
+               Bit 30  Bit 28  Interpretation for Horizontal Text
+               0       0       The subtable is processed in layout order
+                               (the same order as the glyphs, which is
+                               always left-to-right).
+               1       0       The subtable is processed in reverse layout order
+                               (the order opposite that of the glyphs, which is
+                               always right-to-left).
+               0       1       The subtable is processed in logical order
+                               (the same order as the characters, which may be
+                               left-to-right or right-to-left).
+               1       1       The subtable is processed in reverse logical order
+                               (the order opposite that of the characters, which
+                               may be right-to-left or left-to-right).
+       */
+      reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
+               bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
+               bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
+               HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
       if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
-      {
-       c->set_lookup_index (c->lookup_index + 1);
-       continue;
-      }
+        goto skip;
+
+      if (reverse)
+        c->buffer->reverse ();
 
       subtable->apply (c);
-      subtable = &StructAfter<ChainSubtable> (*subtable);
+
+      if (reverse)
+        c->buffer->reverse ();
 
       (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
 
+      if (unlikely (!c->buffer->successful)) return;
+
+    skip:
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
       c->set_lookup_index (c->lookup_index + 1);
     }
   }
 
-  inline unsigned int get_size (void) const { return length; }
+  unsigned int get_size () const { return length; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     if (!length.sanitize (c) ||
@@ -648,16 +1046,16 @@ struct Chain
        !c->check_range (this, length))
       return_trace (false);
 
-    if (!c->check_array (featureZ, featureZ[0].static_size, featureCount))
+    if (!c->check_array (featureZ.arrayZ, featureCount))
       return_trace (false);
 
-    const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (featureZ, featureZ[0].static_size * featureCount);
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
       if (!subtable->sanitize (c))
        return_trace (false);
-      subtable = &StructAfter<ChainSubtable> (*subtable);
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
     }
 
     return_trace (true);
@@ -666,69 +1064,95 @@ struct Chain
   protected:
   HBUINT32     defaultFlags;   /* The default specification for subtables. */
   HBUINT32     length;         /* Total byte count, including this header. */
-  HBUINT32     featureCount;   /* Number of feature subtable entries. */
-  HBUINT32     subtableCount;  /* The number of subtables in the chain. */
+  HBUINT       featureCount;   /* Number of feature subtable entries. */
+  HBUINT       subtableCount;  /* The number of subtables in the chain. */
 
-  Feature      featureZ[VAR];  /* Features. */
-/*ChainSubtable        subtableX[VAR];*//* Subtables. */
-/*subtableGlyphCoverageArray*/ /* Only if major == 3. */
+  UnsizedArrayOf<Feature>      featureZ;       /* Features. */
+/*ChainSubtable        firstSubtable;*//* Subtables. */
+/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
 
   public:
-  DEFINE_SIZE_MIN (16);
+  DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
 };
 
 
 /*
- * The 'mort'/'morx' Tables
+ * The 'mort'/'morx' Table
  */
 
-struct morx
+template <typename Types>
+struct mortmorx
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_morx;
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+
+  bool has_data () const { return version != 0; }
+
+  void compile_flags (const hb_aat_map_builder_t *mapper,
+                     hb_aat_map_t *map) const
+  {
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      map->chain_flags.push (chain->compile_flags (mapper));
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+  }
 
-  inline void apply (hb_aat_apply_context_t *c) const
+  void apply (hb_aat_apply_context_t *c) const
   {
+    if (unlikely (!c->buffer->successful)) return;
     c->set_lookup_index (0);
-    const Chain *chain = chainsZ;
+    const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
-      chain->apply (c);
-      chain = &StructAfter<Chain> (*chain);
+      chain->apply (c, c->plan->aat_map.chain_flags[i]);
+      if (unlikely (!c->buffer->successful)) return;
+      chain = &StructAfter<Chain<Types> > (*chain);
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!version.sanitize (c) ||
-       (version.major >> (sizeof (HBUINT32) == 4 ? 1 : 0)) != 1 ||
-       !chainCount.sanitize (c))
+    if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
       return_trace (false);
 
-    const Chain *chain = chainsZ;
+    const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
-      if (!chain->sanitize (c, version.major))
+      if (!chain->sanitize (c, version))
        return_trace (false);
-      chain = &StructAfter<Chain> (*chain);
+      chain = &StructAfter<Chain<Types> > (*chain);
     }
 
     return_trace (true);
   }
 
   protected:
-  FixedVersion<>version;       /* Version number of the glyph metamorphosis table.
-                                * 1 for mort, 2 or 3 for morx. */
+  HBUINT16     version;        /* Version number of the glyph metamorphosis table.
+                                * 1, 2, or 3. */
+  HBUINT16     unused;         /* Set to 0. */
   HBUINT32     chainCount;     /* Number of metamorphosis chains contained in this
                                 * table. */
-  Chain                chainsZ[VAR];   /* Chains. */
+  Chain<Types> firstChain;     /* Chains. */
 
   public:
   DEFINE_SIZE_MIN (8);
 };
 
+struct morx : mortmorx<ExtendedTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx<ObsoleteTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_mort;
+};
+
+
 } /* namespace AAT */
 
 
diff --git a/src/hb-aat-layout-private.hh b/src/hb-aat-layout-private.hh
deleted file mode 100644 (file)
index ce75c8e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright © 2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_AAT_LAYOUT_PRIVATE_HH
-#define HB_AAT_LAYOUT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-open-type-private.hh"
-
-
-HB_INTERNAL void
-hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer);
-
-HB_INTERNAL void
-hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer);
-
-#endif /* HB_AAT_LAYOUT_PRIVATE_HH */
index 0617e23..0c8e455 100644 (file)
@@ -28,9 +28,9 @@
 #ifndef HB_AAT_LAYOUT_TRAK_TABLE_HH
 #define HB_AAT_LAYOUT_TRAK_TABLE_HH
 
-#include "hb-aat-layout-common-private.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-open-type-private.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
 
 /*
  * trak -- Tracking
@@ -46,29 +46,27 @@ struct TrackTableEntry
 {
   friend struct TrackData;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base,
-                       unsigned int size) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         (valuesZ.sanitize (c, base, size))));
-  }
+  float get_track_value () const { return track.to_float (); }
 
-  private:
-  inline float get_track_value () const
-  {
-    return track.to_float ();
-  }
+  int get_value (const void *base, unsigned int index,
+                unsigned int table_size) const
+  { return (base+valuesZ).as_array (table_size)[index]; }
 
-  inline int get_value (const void *base, unsigned int index) const
+  public:
+  bool sanitize (hb_sanitize_context_t *c, const void *base,
+                unsigned int table_size) const
   {
-    return (base+valuesZ)[index];
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         (valuesZ.sanitize (c, base, table_size))));
   }
 
   protected:
   Fixed                track;          /* Track value for this record. */
-  NameID       trackNameID;    /* The 'name' table index for this track */
-  OffsetTo<UnsizedArrayOf<FWORD> >
+  NameID       trackNameID;    /* The 'name' table index for this track.
+                                * (a short word or phrase like "loose"
+                                * or "very tight") */
+  NNOffsetTo<UnsizedArrayOf<FWORD> >
                valuesZ;        /* Offset from start of tracking table to
                                 * per-size tracking values for this track. */
 
@@ -78,15 +76,22 @@ struct TrackTableEntry
 
 struct TrackData
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  float interpolate_at (unsigned int idx,
+                       float target_size,
+                       const TrackTableEntry &trackTableEntry,
+                       const void *base) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 sizeTable.sanitize (c, base, nSizes) &&
-                 trackTable.sanitize (c, nTracks, base, nSizes));
+    unsigned int sizes = nSizes;
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
+
+    float s0 = size_table[idx].to_float ();
+    float s1 = size_table[idx + 1].to_float ();
+    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
+    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
+          (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
   }
 
-  inline float get_tracking (const void *base, float ptem) const
+  int get_tracking (const void *base, float ptem) const
   {
     /* CoreText points are CSS pixels (96 per inch),
      * NOT typographic points (72 per inch).
@@ -94,48 +99,58 @@ struct TrackData
      * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
      */
     float csspx = ptem * 96.f / 72.f;
-    Fixed fixed_size;
-    fixed_size.set_float (csspx);
 
-    /* XXX Clean this up. Make it work with nSizes==1 and 0. */
+    /*
+     * Choose track.
+     */
+    const TrackTableEntry *trackTableEntry = nullptr;
+    unsigned int count = nTracks;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      /* Note: Seems like the track entries are sorted by values.  But the
+       * spec doesn't explicitly say that.  It just mentions it in the example. */
 
-    unsigned int sizes = nSizes;
+      /* For now we only seek for track entries with zero tracking value */
 
-    const TrackTableEntry *trackTableEntry = nullptr;
-    for (unsigned int i = 0; i < sizes; ++i)
-      // For now we only seek for track entries with zero tracking value
       if (trackTable[i].get_track_value () == 0.f)
-        trackTableEntry = &trackTable[0];
-
-    // We couldn't match any, exit
+      {
+       trackTableEntry = &trackTable[i];
+       break;
+      }
+    }
     if (!trackTableEntry) return 0.;
 
-    /* TODO bfind() */
+    /*
+     * Choose size.
+     */
+    unsigned int sizes = nSizes;
+    if (!sizes) return 0.;
+    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
+
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
     unsigned int size_index;
-    UnsizedArrayOf<Fixed> size_table = base+sizeTable;
-    for (size_index = 0; size_index < sizes; ++size_index)
-      if (size_table[size_index] >= fixed_size)
+    for (size_index = 0; size_index < sizes - 1; size_index++)
+      if (size_table[size_index].to_float () >= csspx)
         break;
 
-    // TODO(ebraminio): We don't attempt to extrapolate to larger or
-    // smaller values for now but we should do, per spec
-    if (size_index == sizes)
-      return trackTableEntry->get_value (base, sizes - 1);
-    if (size_index == 0 || size_table[size_index] == fixed_size)
-      return trackTableEntry->get_value (base, size_index);
-
-    float s0 = size_table[size_index - 1].to_float ();
-    float s1 = size_table[size_index].to_float ();
-    float t = (csspx - s0) / (s1 - s0);
-    return (float) t * trackTableEntry->get_value (base, size_index) +
-          ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1);
+    return round (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+                                 *trackTableEntry, base));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         sizeTable.sanitize (c, base, nSizes) &&
+                         trackTable.sanitize (c, nTracks, base, nSizes)));
   }
 
   protected:
   HBUINT16     nTracks;        /* Number of separate tracks included in this table. */
   HBUINT16     nSizes;         /* Number of point sizes included in this table. */
-  LOffsetTo<UnsizedArrayOf<Fixed> >
-               sizeTable;      /* Offset to array[nSizes] of size values. */
+  LOffsetTo<UnsizedArrayOf<Fixed>, false>
+               sizeTable;      /* Offset from start of the tracking table to
+                                * Array[nSizes] of size values.. */
   UnsizedArrayOf<TrackTableEntry>
                trackTable;     /* Array[nTracks] of TrackTableEntry records. */
 
@@ -145,21 +160,16 @@ struct TrackData
 
 struct trak
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_trak;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak;
 
-    return_trace (unlikely (c->check_struct (this) &&
-                           horizData.sanitize (c, this, this) &&
-                           vertData.sanitize (c, this, this)));
-  }
+  bool has_data () const { return version.to_int (); }
 
-  inline bool apply (hb_aat_apply_context_t *c) const
+  bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
+    hb_mask_t trak_mask = c->plan->trak_mask;
+
     const float ptem = c->font->ptem;
     if (unlikely (ptem <= 0.f))
       return_trace (false);
@@ -168,41 +178,57 @@ struct trak
     if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
     {
       const TrackData &trackData = this+horizData;
-      float tracking = trackData.get_tracking (this, ptem);
-      hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
       foreach_grapheme (buffer, start, end)
       {
-       /* TODO This is wrong. */
+        if (!(buffer->info[start].mask & trak_mask)) continue;
        buffer->pos[start].x_advance += advance_to_add;
-       buffer->pos[end].x_advance += advance_to_add;
+       buffer->pos[start].x_offset += offset_to_add;
       }
     }
     else
     {
       const TrackData &trackData = this+vertData;
-      float tracking = trackData.get_tracking (this, ptem);
-      hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
       foreach_grapheme (buffer, start, end)
       {
-       /* TODO This is wrong. */
+        if (!(buffer->info[start].mask & trak_mask)) continue;
        buffer->pos[start].y_advance += advance_to_add;
-       buffer->pos[end].y_advance += advance_to_add;
+       buffer->pos[start].y_offset += offset_to_add;
       }
     }
 
     return_trace (true);
   }
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                         version.major == 1 &&
+                         horizData.sanitize (c, this, this) &&
+                         vertData.sanitize (c, this, this)));
+  }
+
   protected:
-  FixedVersion<>       version;        /* Version of the tracking table--currently
-                                        * 0x00010000u for version 1.0. */
-  HBUINT16             format;         /* Format of the tracking table */
-  OffsetTo<TrackData>  horizData;      /* TrackData for horizontal text */
-  OffsetTo<TrackData>  vertData;       /* TrackData for vertical text */
-  HBUINT16             reserved;       /* Reserved. Set to 0. */
+  FixedVersion<>version;       /* Version of the tracking table
+                                        * (0x00010000u for version 1.0). */
+  HBUINT16     format;         /* Format of the tracking table (set to 0). */
+  OffsetTo<TrackData>
+               horizData;      /* Offset from start of tracking table to TrackData
+                                * for horizontal text (or 0 if none). */
+  OffsetTo<TrackData>
+               vertData;       /* Offset from start of tracking table to TrackData
+                                * for vertical text (or 0 if none). */
+  HBUINT16     reserved;       /* Reserved. Set to 0. */
 
   public:
-  DEFINE_SIZE_MIN (12);
+  DEFINE_SIZE_STATIC (12);
 };
 
 } /* namespace AAT */
index 7784fae..5168a9c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2017  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
-
-#include "hb-aat-layout-private.hh"
+#include "hb-ot-face.hh"
+#include "hb-aat-layout.hh"
+#include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-layout-ankr-table.hh"
 #include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-aat-layout-feat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-layout-feat-table.hh"
+#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-layout-kerx-table.hh"
 #include "hb-aat-layout-morx-table.hh"
 #include "hb-aat-layout-trak-table.hh"
-#include "hb-aat-fmtx-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-aat-gcid-table.hh" // Just so we compile it; unused otherwise.
-#include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-ltag-table.hh"
+
+
+/**
+ * SECTION:hb-aat-layout
+ * @title: hb-aat-layout
+ * @short_description: Apple Advanced Typography Layout
+ * @include: hb-aat.h
+ *
+ * Functions for querying OpenType Layout features in the font face.
+ **/
+
+
+/* Table data courtesy of Apple.  Converted from mnemonics to integers
+ * when moving to this file. */
+static const hb_aat_feature_mapping_t feature_mappings[] =
+{
+  {HB_TAG ('a','f','r','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('c','2','p','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','2','s','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF},
+  {HB_TAG ('c','a','s','e'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF},
+  {HB_TAG ('c','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF},
+  {HB_TAG ('c','p','s','p'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF},
+  {HB_TAG ('c','s','w','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('d','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON,              HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF},
+  {HB_TAG ('e','x','p','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS,              (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
+  {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL,                HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
+  {HB_TAG ('h','o','j','o'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS,                (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('h','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('i','t','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF},
+  {HB_TAG ('j','p','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','7','8'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','8','3'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','9','0'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('l','i','g','a'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF},
+  {HB_TAG ('l','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('m','g','r','k'), HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS,     HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF},
+  {HB_TAG ('n','l','c','k'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS,                  (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('o','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('o','r','d','n'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS,                       HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('p','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','c','a','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('p','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS,           (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT,             (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
+  {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('s','m','p','l'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS,          (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('s','s','0','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF},
+  {HB_TAG ('s','s','0','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF},
+  {HB_TAG ('s','s','0','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF},
+  {HB_TAG ('s','s','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF},
+  {HB_TAG ('s','s','0','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF},
+  {HB_TAG ('s','s','0','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF},
+  {HB_TAG ('s','s','0','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF},
+  {HB_TAG ('s','s','0','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF},
+  {HB_TAG ('s','s','0','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF},
+  {HB_TAG ('s','s','1','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF},
+  {HB_TAG ('s','s','1','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF},
+  {HB_TAG ('s','s','1','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF},
+  {HB_TAG ('s','s','1','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF},
+  {HB_TAG ('s','s','1','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF},
+  {HB_TAG ('s','s','1','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF},
+  {HB_TAG ('s','s','1','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF},
+  {HB_TAG ('s','s','1','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON,     HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF},
+  {HB_TAG ('s','s','1','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF},
+  {HB_TAG ('s','s','1','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF},
+  {HB_TAG ('s','s','2','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF},
+  {HB_TAG ('s','u','b','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','u','p','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','w','s','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('t','i','t','l'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS},
+  {HB_TAG ('t','n','a','m'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS,   (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS,             (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('t','r','a','d'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS,         (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT,               (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('u','n','i','c'), HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE,             (hb_aat_layout_feature_selector_t) 14,                 (hb_aat_layout_feature_selector_t) 15},
+  {HB_TAG ('v','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','e','r','t'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+  {HB_TAG ('v','h','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
+  {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+  {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,                HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
+};
+
+const hb_aat_feature_mapping_t *
+hb_aat_layout_find_feature_mapping (hb_tag_t tag)
+{
+  return (const hb_aat_feature_mapping_t *) bsearch (&tag,
+                                                    feature_mappings,
+                                                    ARRAY_LENGTH (feature_mappings),
+                                                    sizeof (feature_mappings[0]),
+                                                    hb_aat_feature_mapping_t::cmp);
+}
+
 
 /*
- * morx/kerx/trak
+ * hb_aat_apply_context_t
  */
 
-#if 0
-static inline const AAT::ankr&
-_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
+AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+                                                    hb_font_t *font_,
+                                                    hb_buffer_t *buffer_,
+                                                    hb_blob_t *blob) :
+                                                      plan (plan_),
+                                                      font (font_),
+                                                      face (font->face),
+                                                      buffer (buffer_),
+                                                      sanitizer (),
+                                                      ankr_table (&Null(AAT::ankr)),
+                                                      lookup_index (0),
+                                                      debug_depth (0)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
-  {
-    if (blob)
-      *blob = hb_blob_get_empty ();
-    return Null(AAT::ankr);
-  }
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  const AAT::ankr& ankr = *(layout->ankr.get ());
-  if (blob)
-    *blob = layout->ankr.blob;
-  return ankr;
+  sanitizer.init (blob);
+  sanitizer.set_num_glyphs (face->get_num_glyphs ());
+  sanitizer.start_processing ();
+  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
 }
 
-static inline const AAT::kerx&
-_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
+AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
+{ sanitizer.end_processing (); }
+
+void
+AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
+{ ankr_table = ankr_table_; }
+
+
+/*
+ * mort/morx/kerx/trak
+ */
+
+
+void
+hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                          hb_aat_map_t *map)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  const AAT::morx& morx = *mapper->face->table.morx;
+  if (morx.has_data ())
   {
-    if (blob)
-      *blob = hb_blob_get_empty ();
-    return Null(AAT::kerx);
+    morx.compile_flags (mapper, map);
+    return;
   }
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  /* XXX this doesn't call set_num_glyphs on sanitizer. */
-  const AAT::kerx& kerx = *(layout->kerx.get ());
-  if (blob)
-    *blob = layout->kerx.blob;
-  return kerx;
-}
 
-static inline const AAT::morx&
-_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  const AAT::mort& mort = *mapper->face->table.mort;
+  if (mort.has_data ())
   {
-    if (blob)
-      *blob = hb_blob_get_empty ();
-    return Null(AAT::morx);
+    mort.compile_flags (mapper, map);
+    return;
   }
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  /* XXX this doesn't call set_num_glyphs on sanitizer. */
-  const AAT::morx& morx = *(layout->morx.get ());
-  if (blob)
-    *blob = layout->morx.blob;
-  return morx;
 }
 
-static inline const AAT::trak&
-_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
+
+/*
+ * hb_aat_layout_has_substitution:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face)
+{
+  return face->table.morx->has_data () ||
+        face->table.mort->has_data ();
+}
+
+void
+hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+                         hb_font_t *font,
+                         hb_buffer_t *buffer)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
+  const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
+  if (morx.has_data ())
   {
-    if (blob)
-      *blob = hb_blob_get_empty ();
-    return Null(AAT::trak);
+    AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
+    morx.apply (&c);
+    return;
   }
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  const AAT::trak& trak = *(layout->trak.get ());
-  if (blob)
-    *blob = layout->trak.blob;
-  return trak;
-}
-#endif
-
-// static inline void
-// _hb_aat_layout_create (hb_face_t *face)
-// {
-//   OT::Sanitizer<AAT::morx> sanitizer;
-//   sanitizer.set_num_glyphs (face->get_num_glyphs ());
-//   hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_morx));
-//   morx_blob->as<AAT::morx> ();
-
-//   if (0)
-//   {
-//     morx_blob->as<AAT::Lookup<OT::GlyphID> > ()->get_value (1, face->get_num_glyphs ());
-//   }
-// }
+
+  hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
+  const AAT::mort& mort = *mort_blob->as<AAT::mort> ();
+  if (mort.has_data ())
+  {
+    AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
+    mort.apply (&c);
+    return;
+  }
+}
 
 void
-hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
 {
-#if 0
-  hb_blob_t *blob;
-  const AAT::morx& morx = _get_morx (font->face, &blob);
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  for (unsigned int i = 0; i < count; i++)
+    if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
+      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
+}
 
-  AAT::hb_aat_apply_context_t c (font, buffer, blob);
-  morx.apply (&c);
-#endif
+static bool
+is_deleted_glyph (const hb_glyph_info_t *info)
+{
+  return info->codepoint == AAT::DELETED_GLYPH;
 }
 
 void
-hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer)
+hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
 {
-#if 0
-  hb_blob_t *blob;
-  const AAT::ankr& ankr = _get_ankr (font->face, &blob);
-  const AAT::kerx& kerx = _get_kerx (font->face, &blob);
-  const AAT::trak& trak = _get_trak (font->face, &blob);
+  hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
+}
 
-  AAT::hb_aat_apply_context_t c (font, buffer, blob);
-  kerx.apply (&c, &ankr);
+/*
+ * hb_aat_layout_has_positioning:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_positioning (hb_face_t *face)
+{
+  return face->table.kerx->has_data ();
+}
+
+void
+hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                       hb_font_t *font,
+                       hb_buffer_t *buffer)
+{
+  hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
+  const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
+  c.set_ankr_table (font->face->table.ankr.get ());
+  kerx.apply (&c);
+}
+
+
+/*
+ * hb_aat_layout_has_tracking:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face)
+{
+  return face->table.trak->has_data ();
+}
+
+void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+                    hb_font_t *font,
+                    hb_buffer_t *buffer)
+{
+  const AAT::trak& trak = *font->face->table.trak;
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer);
   trak.apply (&c);
-#endif
+}
+
+
+hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                     unsigned int i)
+{
+  return face->table.ltag->get_language (i);
+}
+
+/**
+ * hb_aat_layout_get_feature_types:
+ * @face: a face object
+ * @start_offset: iteration's start offset
+ * @feature_count:(inout) (allow-none): buffer size as input, filled size as output
+ * @features: (out caller-allocates) (array length=feature_count): features buffer
+ *
+ * Return value: Number of all available feature types.
+ *
+ * Since: 2.2.0
+ */
+unsigned int
+hb_aat_layout_get_feature_types (hb_face_t                    *face,
+                                unsigned int                  start_offset,
+                                unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
+                                hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
+{
+  return face->table.feat->get_feature_types (start_offset, feature_count, features);
+}
+
+/**
+ * hb_aat_layout_feature_type_get_name_id:
+ * @face: a face object
+ * @feature_type: feature id
+ *
+ * Return value: Name ID index
+ *
+ * Since: 2.2.0
+ */
+hb_ot_name_id_t
+hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
+                                       hb_aat_layout_feature_type_t  feature_type)
+{
+  return face->table.feat->get_feature_name_id (feature_type);
+}
+
+/**
+ * hb_aat_layout_feature_type_get_selectors:
+ * @face:    a face object
+ * @feature_type: feature id
+ * @start_offset:    iteration's start offset
+ * @selector_count: (inout) (allow-none): buffer size as input, filled size as output
+ * @selectors: (out caller-allocates) (array length=selector_count): settings buffer
+ * @default_index: (out) (allow-none): index of default selector if any
+ *
+ * If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then
+ * the feature type is non-exclusive.  Otherwise, @default_index is the index of
+ * the selector that is selected by default.
+ *
+ * Return value: Number of all available feature selectors.
+ *
+ * Since: 2.2.0
+ */
+unsigned int
+hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
+                                              hb_aat_layout_feature_type_t           feature_type,
+                                              unsigned int                           start_offset,
+                                              unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
+                                              hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
+                                              unsigned int                          *default_index   /* OUT.     May be NULL. */)
+{
+  return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
 }
diff --git a/src/hb-aat-layout.h b/src/hb-aat-layout.h
new file mode 100644 (file)
index 0000000..760aaae
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_H_IN
+#error "Include <hb-aat.h> instead."
+#endif
+
+#ifndef HB_AAT_LAYOUT_H
+#define HB_AAT_LAYOUT_H
+
+#include "hb.h"
+
+#include "hb-ot.h"
+
+HB_BEGIN_DECLS
+
+/**
+ * hb_aat_layout_feature_type_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_TYPE_INVALID                           = 0xFFFF,
+
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC                   = 0,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES                         = 1,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION                        = 2,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE                       = 3,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION             = 4,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT          = 5,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING                    = 6,
+  HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE                  = 8,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE                   = 9,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION                 = 10,
+  HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS                         = 11,
+  HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE       = 13,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS                        = 14,
+  HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS               = 15,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE                        = 16,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES            = 17,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE            = 18,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS                     = 19,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE                   = 20,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE                       = 21,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING                      = 22,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION                   = 23,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE                   = 24,
+  HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE                 = 25,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE          = 26,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE                = 27,
+  HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA                         = 28,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE      = 29,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE     = 30,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE = 31,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN                  = 32,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT             = 33,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA                    = 34,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES            = 35,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES           = 36,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE                                = 37,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE                                = 38,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE                 = 39,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE            = 103,
+
+  _HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_type_t;
+
+/**
+ * hb_aat_layout_feature_selector_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID                       = 0xFFFF,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF         = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON         = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF            = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON                      = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF                     = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON             = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF            = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON                = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF       = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON          = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF         = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON   = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF  = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON           = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF          = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON       = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF      = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON       = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF      = 21,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED                   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED           = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE                       = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE          = 0, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS                      = 1, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE                        = 2, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS                    = 3, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS                  = 4, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS   = 5, /* deprecated */
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF  = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS         = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON         = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF                = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON       = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF      = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON         = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF                = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON          = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF         = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS               = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS               = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS          = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION               = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS                     = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS                     = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS                      = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS          = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS            = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF           = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON         = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON          = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF         = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON               = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF              = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON           = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF          = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON               = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF              = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON                = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF       = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF           = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON       = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF      = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF           = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON       = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF      = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON                  = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF                 = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF                = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS                      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS                 = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS                      = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS         = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS                  = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES                 = 0,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1                 = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2                 = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3                 = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4                 = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5                 = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS              = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT                  = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT                 = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS              = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS                  = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS                     = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS            = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE           = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO           = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE         = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR          = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE          = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS             = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS            = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS               = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS                 = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS  = 14,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS            = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT               = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT               = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT              = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT         = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT           = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL               = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA          = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION          = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA      = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA      = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO       = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE     = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION                 = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION                        = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION                = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION             = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION    = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION                = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION             = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION      = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION            = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION       = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION= 10,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA               = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA             = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS         = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS         = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON      = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF     = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON    = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF   = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA                  = 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA                     = 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF                 = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE           = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE           = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE         = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR          = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE          = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE  = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN           = 0,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN              = 1,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF          = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON      = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF     = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON     = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF    = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON                = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF       = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON          = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF         = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON          = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF         = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON                = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON         = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF                = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF                = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON          = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF         = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON                = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF       = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON                = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF       = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON         = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF                = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON          = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF         = 21,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON       = 22,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF      = 23,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON       = 24,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF      = 25,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON     = 26,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF    = 27,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON     = 28,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF    = 29,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON      = 30,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF     = 31,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON      = 32,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF     = 33,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON    = 34,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF   = 35,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON     = 36,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF    = 37,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON     = 38,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF    = 39,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON       = 40,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF      = 41,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON      = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF     = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON        = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF= 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS                = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE            = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS                = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN             = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN          = 3,
+
+  _HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_selector_t;
+
+HB_EXTERN unsigned int
+hb_aat_layout_get_feature_types (hb_face_t                    *face,
+                                unsigned int                  start_offset,
+                                unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
+                                hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */);
+
+HB_EXTERN hb_ot_name_id_t
+hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
+                                       hb_aat_layout_feature_type_t  feature_type);
+
+typedef struct hb_aat_layout_feature_selector_info_t
+{
+  hb_ot_name_id_t                      name_id;
+  hb_aat_layout_feature_selector_t     enable;
+  hb_aat_layout_feature_selector_t     disable;
+  /*< private >*/
+  unsigned int                         reserved;
+} hb_aat_layout_feature_selector_info_t;
+
+#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX                0xFFFFu
+
+HB_EXTERN unsigned int
+hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
+                                              hb_aat_layout_feature_type_t           feature_type,
+                                              unsigned int                           start_offset,
+                                              unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
+                                              hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
+                                              unsigned int                          *default_index   /* OUT.     May be NULL. */);
+
+
+/*
+ * morx/mort
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face);
+
+
+/*
+ * kerx
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_positioning (hb_face_t *face);
+
+
+/*
+ * trak
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face);
+
+
+HB_END_DECLS
+
+#endif /* HB_AAT_LAYOUT_H */
diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh
new file mode 100644 (file)
index 0000000..8346d9f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_HH
+#define HB_AAT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+struct hb_aat_feature_mapping_t
+{
+  hb_tag_t otFeatureTag;
+  hb_aat_layout_feature_type_t aatFeatureType;
+  hb_aat_layout_feature_selector_t selectorToEnable;
+  hb_aat_layout_feature_selector_t selectorToDisable;
+
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (unsigned int *) key_;
+    const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
+    return key < entry->otFeatureTag ? -1 :
+          key > entry->otFeatureTag ? 1 :
+          0;
+  }
+};
+
+HB_INTERNAL const hb_aat_feature_mapping_t *
+hb_aat_layout_find_feature_mapping (hb_tag_t tag);
+
+HB_INTERNAL void
+hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                          hb_aat_map_t *map);
+
+HB_INTERNAL void
+hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+                         hb_font_t *font,
+                         hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                       hb_font_t *font,
+                       hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+                    hb_font_t *font,
+                    hb_buffer_t *buffer);
+
+HB_INTERNAL hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                     unsigned int i);
+
+
+#endif /* HB_AAT_LAYOUT_HH */
index 15c4e89..6f34a00 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_AAT_LTAG_TABLE_HH
 #define HB_AAT_LTAG_TABLE_HH
 
-#include "hb-aat-layout-common-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * ltag -- Language Tag
 
 namespace AAT {
 
+using namespace OT;
+
 
 struct FTStringRange
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  friend struct ltag;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
   }
 
   protected:
-  OffsetTo<UnsizedArrayOf<HBUINT8> >
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
                tag;            /* Offset from the start of the table to
                                 * the beginning of the string */
   HBUINT16     length;         /* String length (in bytes) */
@@ -56,12 +60,21 @@ struct FTStringRange
 
 struct ltag
 {
-  static const hb_tag_t tableTag = HB_AAT_TAG_ltag;
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ltag;
+
+  hb_language_t get_language (unsigned int i) const
+  {
+    const FTStringRange &range = tagRanges[i];
+    return hb_language_from_string ((const char *) (this+range.tag).arrayZ,
+                                   range.length);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && tagRanges.sanitize (c, this)));
+    return_trace (likely (c->check_struct (this) &&
+                         version >= 1 &&
+                         tagRanges.sanitize (c, this)));
   }
 
   protected:
diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc
new file mode 100644 (file)
index 0000000..98c5d7f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2013  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
+ */
+
+#include "hb-aat-map.hh"
+
+#include "hb-aat-layout.hh"
+
+
+void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
+                                       unsigned int value)
+{
+  if (tag == HB_TAG ('a','a','l','t'))
+  {
+    feature_info_t *info = features.push();
+    info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
+    info->setting = (hb_aat_layout_feature_selector_t) value;
+    return;
+  }
+
+  const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
+  if (!mapping) return;
+
+  feature_info_t *info = features.push();
+  info->type = mapping->aatFeatureType;
+  info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
+}
+
+void
+hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
+{
+  /* Sort features and merge duplicates */
+  if (features.length)
+  {
+    features.qsort ();
+    unsigned int j = 0;
+    for (unsigned int i = 1; i < features.length; i++)
+      if (features[i].type != features[j].type)
+       features[++j] = features[i];
+    features.shrink (j + 1);
+  }
+
+  hb_aat_layout_compile_map (this, &m);
+}
diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh
new file mode 100644 (file)
index 0000000..3d5ad0e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_MAP_HH
+#define HB_AAT_MAP_HH
+
+#include "hb.hh"
+
+
+struct hb_aat_map_t
+{
+  friend struct hb_aat_map_builder_t;
+
+  public:
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+    chain_flags.init ();
+  }
+  void fini () { chain_flags.fini (); }
+
+  public:
+  hb_vector_t<hb_mask_t> chain_flags;
+};
+
+struct hb_aat_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
+                                   const hb_segment_properties_t *props_ HB_UNUSED) :
+                                     face (face_) {}
+
+  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
+
+  HB_INTERNAL void compile (hb_aat_map_t  &m);
+
+  public:
+  struct feature_info_t
+  {
+    hb_aat_layout_feature_type_t  type;
+    hb_aat_layout_feature_selector_t  setting;
+    unsigned  seq; /* For stable sorting only. */
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const feature_info_t *a = (const feature_info_t *) pa;
+      const feature_info_t *b = (const feature_info_t *) pb;
+      return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
+            (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+
+    int cmp (hb_aat_layout_feature_type_t ty) const
+    {
+      return (type != ty) ? (type < ty ? -1 : 1) : 0;
+    }
+  };
+
+  public:
+  hb_face_t *face;
+
+  public:
+  hb_vector_t<feature_info_t> features;
+};
+
+
+#endif /* HB_AAT_MAP_HH */
diff --git a/src/hb-aat.h b/src/hb-aat.h
new file mode 100644 (file)
index 0000000..c14313d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_AAT_H
+#define HB_AAT_H
+#define HB_AAT_H_IN
+
+#include "hb.h"
+
+#include "hb-aat-layout.h"
+
+HB_BEGIN_DECLS
+
+HB_END_DECLS
+
+#undef HB_AAT_H_IN
+#endif /* HB_AAT_H */
diff --git a/src/hb-array.hh b/src/hb-array.hh
new file mode 100644 (file)
index 0000000..52b775e
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ARRAY_HH
+#define HB_ARRAY_HH
+
+#include "hb.hh"
+#include "hb-dsalgs.hh"
+#include "hb-iter.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_sorted_array_t;
+
+template <typename Type>
+struct hb_array_t :
+       hb_iter_t<hb_array_t<Type>, Type>,
+       hb_iter_mixin_t<hb_array_t<Type>, Type>
+{
+  /*
+   * Constructors.
+   */
+  hb_array_t () : arrayZ (nullptr), length (0) {}
+  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
+  template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
+
+
+  /*
+   * Iterator implementation.
+   */
+  typedef Type __item_type__;
+  Type& __item_at__ (unsigned i) const
+  {
+    if (unlikely (i >= length)) return CrapOrNull (Type);
+    return arrayZ[i];
+  }
+  void __forward__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+    arrayZ += n;
+  }
+  void __rewind__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+  }
+  unsigned __len__ () const { return length; }
+  bool __random_access__ () const { return true; }
+
+  /* Extra operators.
+   */
+  Type * operator & () const { return arrayZ; }
+  operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
+  template <typename T> operator T * () const { return arrayZ; }
+
+  /*
+   * Compare, Sort, and Search.
+   */
+
+  /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
+  int cmp (const hb_array_t<Type> &a) const
+  {
+    if (length != a.length)
+      return (int) a.length - (int) length;
+    return hb_memcmp (a.arrayZ, arrayZ, get_size ());
+  }
+  static int cmp (const void *pa, const void *pb)
+  {
+    hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
+    hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
+    return b->cmp (*a);
+  }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!this->arrayZ[i].cmp (x))
+       return &this->arrayZ[i];
+    return not_found;
+  }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!this->arrayZ[i].cmp (x))
+       return &this->arrayZ[i];
+    return not_found;
+  }
+
+  hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
+  {
+    if (likely (length))
+      ::qsort (arrayZ, length, this->item_size, cmp_);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  hb_sorted_array_t<Type> qsort ()
+  {
+    if (likely (length))
+      ::qsort (arrayZ, length, this->item_size, Type::cmp);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  void qsort (unsigned int start, unsigned int end)
+  {
+    end = MIN (end, length);
+    assert (start <= end);
+    if (likely (start < end))
+      ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
+  }
+
+  /*
+   * Other methods.
+   */
+
+  unsigned int get_size () const { return length * this->item_size; }
+
+  hb_array_t<Type> sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
+  {
+    if (!start_offset && !seg_count)
+      return *this;
+
+    unsigned int count = length;
+    if (unlikely (start_offset > count))
+      count = 0;
+    else
+      count -= start_offset;
+    if (seg_count)
+      count = *seg_count = MIN (count, *seg_count);
+    return hb_array_t<Type> (arrayZ + start_offset, count);
+  }
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  /* Only call if you allocated the underlying array using malloc() or similar. */
+  void free ()
+  { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
+
+  template <typename hb_sanitize_context_t>
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return c->check_array (arrayZ, length); }
+
+  /*
+   * Members
+   */
+
+  public:
+  Type *arrayZ;
+  unsigned int length;
+};
+template <typename T> inline hb_array_t<T>
+hb_array (T *array, unsigned int length)
+{ return hb_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_array_t<T>
+hb_array (T (&array_)[length_])
+{ return hb_array_t<T> (array_); }
+
+
+enum hb_bfind_not_found_t
+{
+  HB_BFIND_NOT_FOUND_DONT_STORE,
+  HB_BFIND_NOT_FOUND_STORE,
+  HB_BFIND_NOT_FOUND_STORE_CLOSEST,
+};
+
+template <typename Type>
+struct hb_sorted_array_t :
+       hb_sorted_iter_t<hb_sorted_array_t<Type>, Type>,
+       hb_array_t<Type>,
+       hb_iter_mixin_t<hb_sorted_array_t<Type>, Type>
+{
+  hb_sorted_array_t () : hb_array_t<Type> () {}
+  hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
+  hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
+  template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
+
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
+  { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                    hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                    unsigned int to_store = (unsigned int) -1) const
+  {
+    int min = 0, max = (int) this->length - 1;
+    const Type *array = this->arrayZ;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      int c = array[mid].cmp (x);
+      if (c < 0)
+        max = mid - 1;
+      else if (c > 0)
+        min = mid + 1;
+      else
+      {
+       if (i)
+         *i = mid;
+       return true;
+      }
+    }
+    if (i)
+    {
+      switch (not_found)
+      {
+       case HB_BFIND_NOT_FOUND_DONT_STORE:
+         break;
+
+       case HB_BFIND_NOT_FOUND_STORE:
+         *i = to_store;
+         break;
+
+       case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+         if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
+           max++;
+         *i = max;
+         break;
+      }
+    }
+    return false;
+  }
+};
+template <typename T> inline hb_sorted_array_t<T>
+hb_sorted_array (T *array, unsigned int length)
+{ return hb_sorted_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
+hb_sorted_array (T (&array_)[length_])
+{ return hb_sorted_array_t<T> (array_); }
+
+
+typedef hb_array_t<const char> hb_bytes_t;
+typedef hb_array_t<const unsigned char> hb_ubytes_t;
+
+
+#endif /* HB_ARRAY_HH */
diff --git a/src/hb-atomic-private.hh b/src/hb-atomic-private.hh
deleted file mode 100644 (file)
index 12caaca..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,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.
- *
- * Contributor(s):
- *     Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_ATOMIC_PRIVATE_HH
-#define HB_ATOMIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* atomic_int */
-
-/* We need external help for these */
-
-#if defined(hb_atomic_int_impl_add) \
- && defined(hb_atomic_ptr_impl_get) \
- && defined(hb_atomic_ptr_impl_cmpexch)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-
-/* MinGW has a convoluted history of supporting MemoryBarrier
- * properly.  As such, define a function to wrap the whole
- * thing. */
-static inline void _HBMemoryBarrier (void) {
-#if !defined(MemoryBarrier)
-  long dummy = 0;
-  InterlockedExchange (&dummy, 1);
-#else
-  MemoryBarrier ();
-#endif
-}
-
-typedef LONG hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          InterlockedExchangeAdd (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)              (_HBMemoryBarrier (), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          __sync_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)              (void *) (__sync_synchronize (), *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      __sync_bool_compare_and_swap ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-typedef unsigned int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)              ( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
-
-
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
-
-#include <libkern/OSAtomic.h>
-#ifdef __MAC_OS_X_MIN_REQUIRED
-#include <AvailabilityMacros.h>
-#elif defined(__IPHONE_OS_MIN_REQUIRED)
-#include <Availability.h>
-#endif
-
-
-typedef int32_t hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)              (OSMemoryBarrier (), (void *) *(P))
-#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
-#else
-#if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
-#else
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
-#endif
-#endif
-
-
-#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
-
-#include <builtins.h>
-
-
-static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
-  __lwsync();
-  int result = __fetch_and_add(AI, V);
-  __isync();
-  return result;
-}
-static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
-  __sync();
-  int result = __compare_and_swaplp (P, &O, N);
-  __sync();
-  return result;
-}
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (__sync(), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
-
-#elif !defined(HB_NO_MT)
-
-#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-
-typedef volatile int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)              ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)          (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)              ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-
-#endif
-
-
-#define HB_ATOMIC_INT_INIT(V)          {V}
-
-struct hb_atomic_int_t
-{
-  hb_atomic_int_impl_t v;
-
-  inline void set_unsafe (int v_) { v = v_; }
-  inline int get_unsafe (void) const { return v; }
-  inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); }
-  inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
-};
-
-
-#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
-#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
-
-
-#endif /* HB_ATOMIC_PRIVATE_HH */
diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh
new file mode 100644 (file)
index 0000000..9321932
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,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.
+ *
+ * Contributor(s):
+ *     Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ATOMIC_HH
+#define HB_ATOMIC_HH
+
+#include "hb.hh"
+
+
+/*
+ * Atomic integers and pointers.
+ */
+
+
+/* We need external help for these */
+
+#if defined(hb_atomic_int_impl_add) \
+ && defined(hb_atomic_ptr_impl_get) \
+ && defined(hb_atomic_ptr_impl_cmpexch)
+
+/* Defined externally, i.e. in config.h. */
+
+
+#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
+
+/* C++11-style GCC primitives. */
+
+#define _hb_memory_barrier()                   __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)          __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
+#define hb_atomic_int_impl_set_relaxed(AI, V)  __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_set(AI, V)          __atomic_store_n ((AI), (V), __ATOMIC_RELEASE)
+#define hb_atomic_int_impl_get_relaxed(AI)     __atomic_load_n ((AI), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_get(AI)             __atomic_load_n ((AI), __ATOMIC_ACQUIRE)
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)   __atomic_store_n ((P), (V), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get_relaxed(P)      __atomic_load_n ((P), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get(P)              __atomic_load_n ((P), __ATOMIC_ACQUIRE)
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
+
+/* C++11 atomics. */
+
+#include <atomic>
+
+#define _hb_memory_barrier()                   std::atomic_thread_fence(std::memory_order_ack_rel)
+#define _hb_memory_r_barrier()                 std::atomic_thread_fence(std::memory_order_acquire)
+#define _hb_memory_w_barrier()                 std::atomic_thread_fence(std::memory_order_release)
+
+#define hb_atomic_int_impl_add(AI, V)          (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V)  (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_set(AI, V)          (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_release))
+#define hb_atomic_int_impl_get_relaxed(AI)     (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
+#define hb_atomic_int_impl_get(AI)             (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_acquire))
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)   (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get_relaxed(P)      (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get(P)              (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+
+static inline void _hb_memory_barrier ()
+{
+#if !defined(MemoryBarrier)
+  /* MinGW has a convoluted history of supporting MemoryBarrier. */
+  LONG dummy = 0;
+  InterlockedExchange (&dummy, 1);
+#else
+  MemoryBarrier ();
+#endif
+}
+#define _hb_memory_barrier()                   _hb_memory_barrier ()
+
+#define hb_atomic_int_impl_add(AI, V)          InterlockedExchangeAdd ((LONG *) (AI), (V))
+static_assert ((sizeof (LONG) == sizeof (int)), "");
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#define _hb_memory_barrier()                   __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)          __sync_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      __sync_bool_compare_and_swap ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
+
+#include <atomic.h>
+#include <mbarrier.h>
+
+#define _hb_memory_r_barrier()                 __machine_r_barrier ()
+#define _hb_memory_w_barrier()                 __machine_w_barrier ()
+#define _hb_memory_barrier()                   __machine_rw_barrier ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_w_barrier ();
+  int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
+  _hb_memory_r_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
+{
+  _hb_memory_w_barrier ();
+  bool result = atomic_cas_ptr (P, O, N) == O;
+  _hb_memory_r_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swap_ptr ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(__APPLE__)
+
+#include <libkern/OSAtomic.h>
+#ifdef __MAC_OS_X_MIN_REQUIRED
+#include <AvailabilityMacros.h>
+#elif defined(__IPHONE_OS_MIN_REQUIRED)
+#include <Availability.h>
+#endif
+
+#define _hb_memory_barrier()                   OSMemoryBarrier ()
+
+#define hb_atomic_int_impl_add(AI, V)          (OSAtomicAdd32Barrier ((V), (AI)) - (V))
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
+#else
+#if __ppc64__ || __x86_64__ || __aarch64__
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
+#else
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
+#endif
+#endif
+
+
+#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__)
+
+#include <builtins.h>
+
+#define _hb_memory_barrier()                   __lwsync ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_barrier ();
+  int result = __fetch_and_add (AI, V);
+  _hb_memory_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
+{
+  _hb_memory_barrier ();
+  bool result = __compare_and_swaplp (P, &O, N);
+  _hb_memory_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
+static_assert ((sizeof (long) == sizeof (void *)), "");
+
+
+#elif !defined(HB_NO_MT)
+
+#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_int_impl_add(AI, V)          ((*(AI) += (V)) - (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#else /* HB_NO_MT */
+
+#define hb_atomic_int_impl_add(AI, V)          ((*(AI) += (V)) - (V))
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)      (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#endif
+
+
+#ifndef _hb_memory_r_barrier
+#define _hb_memory_r_barrier()                 _hb_memory_barrier ()
+#endif
+#ifndef _hb_memory_w_barrier
+#define _hb_memory_w_barrier()                 _hb_memory_barrier ()
+#endif
+#ifndef hb_atomic_int_impl_set_relaxed
+#define hb_atomic_int_impl_set_relaxed(AI, V)  (*(AI) = (V))
+#endif
+#ifndef hb_atomic_int_impl_get_relaxed
+#define hb_atomic_int_impl_get_relaxed(AI)     (*(AI))
+#endif
+
+#ifndef hb_atomic_ptr_impl_set_relaxed
+#define hb_atomic_ptr_impl_set_relaxed(P, V)   (*(P) = (V))
+#endif
+#ifndef hb_atomic_ptr_impl_get_relaxed
+#define hb_atomic_ptr_impl_get_relaxed(P)      (*(P))
+#endif
+#ifndef hb_atomic_int_impl_set
+inline void hb_atomic_int_impl_set (int *AI, int v)    { _hb_memory_w_barrier (); *AI = v; }
+#endif
+#ifndef hb_atomic_int_impl_get
+inline int hb_atomic_int_impl_get (const int *AI)      { int v = *AI; _hb_memory_r_barrier (); return v; }
+#endif
+#ifndef hb_atomic_ptr_impl_get
+inline void *hb_atomic_ptr_impl_get (void ** const P)  { void *v = *P; _hb_memory_r_barrier (); return v; }
+#endif
+
+
+#define HB_ATOMIC_INT_INIT(V)          {V}
+struct hb_atomic_int_t
+{
+  void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+  void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
+  int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+  int get () const { return hb_atomic_int_impl_get (&v); }
+  int inc () { return hb_atomic_int_impl_add (&v,  1); }
+  int dec () { return hb_atomic_int_impl_add (&v, -1); }
+
+  int v;
+};
+
+
+#define HB_ATOMIC_PTR_INIT(V)          {V}
+template <typename P>
+struct hb_atomic_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  void init (T* v_ = nullptr) { set_relaxed (v_); }
+  void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
+  T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
+  T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+  bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+
+  T * operator -> () const                    { return get (); }
+  template <typename C> operator C * () const { return get (); }
+
+  T *v;
+};
+
+
+#endif /* HB_ATOMIC_HH */
diff --git a/src/hb-blob-private.hh b/src/hb-blob-private.hh
deleted file mode 100644 (file)
index b72fa72..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BLOB_PRIVATE_HH
-#define HB_BLOB_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-
-
-/*
- * hb_blob_t
- */
-
-struct hb_blob_t
-{
-  inline void fini_shallow (void)
-  {
-    destroy_user_data ();
-  }
-
-  inline void destroy_user_data (void)
-  {
-    if (destroy)
-    {
-      destroy (user_data);
-      user_data = nullptr;
-      destroy = nullptr;
-    }
-  }
-
-  HB_INTERNAL bool try_make_writable (void);
-  HB_INTERNAL bool try_make_writable_inplace (void);
-  HB_INTERNAL bool try_make_writable_inplace_unix (void);
-
-  inline void lock (void)
-  {
-    hb_blob_make_immutable (this);
-  }
-
-  template <typename Type>
-  inline const Type* as (void) const
-  {
-    return unlikely (!data) ? &Null(Type) : reinterpret_cast<const Type *> (data);
-  }
-
-  public:
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  bool immutable;
-
-  const char *data;
-  unsigned int length;
-  hb_memory_mode_t mode;
-
-  void *user_data;
-  hb_destroy_func_t destroy;
-};
-
-
-#endif /* HB_BLOB_PRIVATE_HH */
index c138648..bcf381e 100644 (file)
  * Red Hat Author(s): Behdad Esfahbod
  */
 
-/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1308
+ * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+ * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
+ */
 #ifndef _POSIX_C_SOURCE
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define _POSIX_C_SOURCE 200809L
+#pragma GCC diagnostic pop
 #endif
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
+#include "hb.hh"
+#include "hb-blob.hh"
 
 #ifdef HAVE_SYS_MMAN_H
 #ifdef HAVE_UNISTD_H
 
 
 /**
+ * SECTION: hb-blob
+ * @title: hb-blob
+ * @short_description: Binary data containers
+ * @include: hb.h
+ *
+ * Blobs wrap a chunk of binary data to handle lifecycle management of data
+ * while it is passed between client and HarfBuzz.  Blobs are primarily used
+ * to create font faces, but also to access font face tables, as well as
+ * pass around other binary data.
+ **/
+
+
+/**
  * hb_blob_create: (skip)
  * @data: Pointer to blob data.
  * @length: Length of @data in bytes.
@@ -130,7 +149,7 @@ hb_blob_create_sub_blob (hb_blob_t    *parent,
 {
   hb_blob_t *blob;
 
-  if (!length || offset >= parent->length)
+  if (!length || !parent || offset >= parent->length)
     return hb_blob_get_empty ();
 
   hb_blob_make_immutable (parent);
@@ -181,22 +200,9 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_blob_get_empty (void)
+hb_blob_get_empty ()
 {
-  static const hb_blob_t _hb_blob_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* data */
-    0, /* length */
-    HB_MEMORY_MODE_READONLY, /* mode */
-
-    nullptr, /* user_data */
-    nullptr  /* destroy */
-  };
-
-  return const_cast<hb_blob_t *> (&_hb_blob_nil);
+  return const_cast<hb_blob_t *> (&Null(hb_blob_t));
 }
 
 /**
@@ -291,10 +297,10 @@ hb_blob_get_user_data (hb_blob_t          *blob,
 void
 hb_blob_make_immutable (hb_blob_t *blob)
 {
-  if (hb_object_is_inert (blob))
+  if (hb_object_is_immutable (blob))
     return;
 
-  blob->immutable = true;
+  hb_object_make_immutable (blob);
 }
 
 /**
@@ -310,7 +316,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
 hb_bool_t
 hb_blob_is_immutable (hb_blob_t *blob)
 {
-  return blob->immutable;
+  return hb_object_is_immutable (blob);
 }
 
 
@@ -384,7 +390,7 @@ hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
 
 
 bool
-hb_blob_t::try_make_writable_inplace_unix (void)
+hb_blob_t::try_make_writable_inplace_unix ()
 {
 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
   uintptr_t pagesize = -1, mask, length;
@@ -427,7 +433,7 @@ hb_blob_t::try_make_writable_inplace_unix (void)
 }
 
 bool
-hb_blob_t::try_make_writable_inplace (void)
+hb_blob_t::try_make_writable_inplace ()
 {
   DEBUG_MSG_FUNC (BLOB, this, "making writable inplace\n");
 
@@ -442,9 +448,9 @@ hb_blob_t::try_make_writable_inplace (void)
 }
 
 bool
-hb_blob_t::try_make_writable (void)
+hb_blob_t::try_make_writable ()
 {
-  if (this->immutable)
+  if (hb_object_is_immutable (this))
     return false;
 
   if (this->mode == HB_MEMORY_MODE_WRITABLE)
@@ -487,12 +493,12 @@ hb_blob_t::try_make_writable (void)
 # include <fcntl.h>
 #endif
 
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
 # include <windows.h>
-#endif
-
-#ifndef _O_BINARY
-# define _O_BINARY 0
+#else
+# ifndef O_BINARY
+#  define O_BINARY 0
+# endif
 #endif
 
 #ifndef MAP_NORESERVE
@@ -503,25 +509,28 @@ struct hb_mapped_file_t
 {
   char *contents;
   unsigned long length;
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
   HANDLE mapping;
 #endif
 };
 
+#if (defined(HAVE_MMAP) || defined(_WIN32)) && !defined(HB_NO_MMAP)
 static void
-_hb_mapped_file_destroy (hb_mapped_file_t *file)
+_hb_mapped_file_destroy (void *file_)
 {
+  hb_mapped_file_t *file = (hb_mapped_file_t *) file_;
 #ifdef HAVE_MMAP
   munmap (file->contents, file->length);
-#elif defined(_WIN32) || defined(__CYGWIN__)
+#elif defined(_WIN32)
   UnmapViewOfFile (file->contents);
   CloseHandle (file->mapping);
 #else
-  free (file->contents);
+  assert (0); // If we don't have mmap we shouldn't reach here
 #endif
 
   free (file);
 }
+#endif
 
 /**
  * hb_blob_create_from_file:
@@ -534,77 +543,136 @@ _hb_mapped_file_destroy (hb_mapped_file_t *file)
 hb_blob_t *
 hb_blob_create_from_file (const char *file_name)
 {
-  // Adopted from glib's gmappedfile.c with Matthias Clasen and
-  // Allison Lortie permission but changed a lot to suit our need.
-  bool writable = false;
-  hb_memory_mode_t mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
+  /* Adopted from glib's gmappedfile.c with Matthias Clasen and
+     Allison Lortie permission but changed a lot to suit our need. */
+#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
   hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
 
-#ifdef HAVE_MMAP
-  int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
-# define CLOSE close
+  int fd = open (file_name, O_RDONLY | O_BINARY, 0);
   if (unlikely (fd == -1)) goto fail_without_close;
 
   struct stat st;
   if (unlikely (fstat (fd, &st) == -1)) goto fail;
 
-  // See https://github.com/GNOME/glib/blob/f9faac7/glib/gmappedfile.c#L139-L142
-  if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
-
   file->length = (unsigned long) st.st_size;
-  file->contents = (char *) mmap (nullptr, file->length,
-                                 writable ? PROT_READ|PROT_WRITE : PROT_READ,
+  file->contents = (char *) mmap (nullptr, file->length, PROT_READ,
                                  MAP_PRIVATE | MAP_NORESERVE, fd, 0);
 
   if (unlikely (file->contents == MAP_FAILED)) goto fail;
 
-#elif defined(_WIN32) || defined(__CYGWIN__)
-  HANDLE fd = CreateFile (file_name,
-                         writable ? GENERIC_READ|GENERIC_WRITE : GENERIC_READ,
-                         FILE_SHARE_READ, nullptr, OPEN_EXISTING,
-                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
-# define CLOSE CloseHandle
+  close (fd);
 
-  if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
+  return hb_blob_create (file->contents, file->length,
+                        HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
+                        (hb_destroy_func_t) _hb_mapped_file_destroy);
 
-  file->length = (unsigned long) GetFileSize (fd, nullptr);
-  file->mapping = CreateFileMapping (fd, nullptr,
-                                    writable ? PAGE_WRITECOPY : PAGE_READONLY,
-                                    0, 0, nullptr);
-  if (unlikely (file->mapping == nullptr)) goto fail;
+fail:
+  close (fd);
+fail_without_close:
+  free (file);
 
-  file->contents = (char *) MapViewOfFile (file->mapping,
-                                          writable ? FILE_MAP_COPY : FILE_MAP_READ,
-                                          0, 0, 0);
-  if (unlikely (file->contents == nullptr)) goto fail;
+#elif defined(_WIN32) && !defined(HB_NO_MMAP)
+  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
+  if (unlikely (!file)) return hb_blob_get_empty ();
 
+  HANDLE fd;
+  unsigned int size = strlen (file_name) + 1;
+  wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
+  if (unlikely (wchar_file_name == nullptr)) goto fail_without_close;
+  mbstowcs (wchar_file_name, file_name, size);
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
+    ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+    ceparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFFF;
+    ceparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFF00000;
+    ceparams.dwSecurityQosFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0x000F0000;
+    ceparams.lpSecurityAttributes = nullptr;
+    ceparams.hTemplateFile = nullptr;
+    fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ,
+                      OPEN_EXISTING, &ceparams);
+  }
 #else
-  mm = HB_MEMORY_MODE_WRITABLE;
-
-  FILE *fd = fopen (file_name, "rb");
-# define CLOSE fclose
-  if (unlikely (!fd)) goto fail_without_close;
+  fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
+                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
+                   nullptr);
+#endif
+  free (wchar_file_name);
 
-  fseek (fd, 0, SEEK_END);
-  file->length = ftell (fd);
-  rewind (fd);
-  file->contents = (char *) malloc (file->length);
-  if (unlikely (!file->contents)) goto fail;
+  if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
 
-  if (unlikely (fread (file->contents, 1, file->length, fd) != file->length))
-    goto fail;
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    LARGE_INTEGER length;
+    GetFileSizeEx (fd, &length);
+    file->length = length.LowPart;
+    file->mapping = CreateFileMappingFromApp (fd, nullptr, PAGE_READONLY, length.QuadPart, nullptr);
+  }
+#else
+  file->length = (unsigned long) GetFileSize (fd, nullptr);
+  file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
+#endif
+  if (unlikely (file->mapping == nullptr)) goto fail;
 
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
+#else
+  file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
 #endif
+  if (unlikely (file->contents == nullptr)) goto fail;
 
-  CLOSE (fd);
-  return hb_blob_create (file->contents, file->length, mm, (void *) file,
+  CloseHandle (fd);
+  return hb_blob_create (file->contents, file->length,
+                        HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
                         (hb_destroy_func_t) _hb_mapped_file_destroy);
 
 fail:
-  CLOSE (fd);
-#undef CLOSE
+  CloseHandle (fd);
 fail_without_close:
   free (file);
+
+#endif
+
+  /* The following tries to read a file without knowing its size beforehand
+     It's used as a fallback for systems without mmap or to read from pipes */
+  unsigned long len = 0, allocated = BUFSIZ * 16;
+  char *data = (char *) malloc (allocated);
+  if (unlikely (data == nullptr)) return hb_blob_get_empty ();
+
+  FILE *fp = fopen (file_name, "rb");
+  if (unlikely (fp == nullptr)) goto fread_fail_without_close;
+
+  while (!feof (fp))
+  {
+    if (allocated - len < BUFSIZ)
+    {
+      allocated *= 2;
+      /* Don't allocate and go more than ~536MB, our mmap reader still
+        can cover files like that but lets limit our fallback reader */
+      if (unlikely (allocated > (2 << 28))) goto fread_fail;
+      char *new_data = (char *) realloc (data, allocated);
+      if (unlikely (new_data == nullptr)) goto fread_fail;
+      data = new_data;
+    }
+
+    unsigned long addition = fread (data + len, 1, allocated - len, fp);
+
+    int err = ferror (fp);
+#ifdef EINTR // armcc doesn't have it
+    if (unlikely (err == EINTR)) continue;
+#endif
+    if (unlikely (err)) goto fread_fail;
+
+    len += addition;
+  }
+
+  return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
+                         (hb_destroy_func_t) free);
+
+fread_fail:
+  fclose (fp);
+fread_fail_without_close:
+  free (data);
   return hb_blob_get_empty ();
 }
diff --git a/src/hb-blob.hh b/src/hb-blob.hh
new file mode 100644 (file)
index 0000000..4ea13f8
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BLOB_HH
+#define HB_BLOB_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_blob_t
+ */
+
+struct hb_blob_t
+{
+  void fini_shallow () { destroy_user_data (); }
+
+  void destroy_user_data ()
+  {
+    if (destroy)
+    {
+      destroy (user_data);
+      user_data = nullptr;
+      destroy = nullptr;
+    }
+  }
+
+  HB_INTERNAL bool try_make_writable ();
+  HB_INTERNAL bool try_make_writable_inplace ();
+  HB_INTERNAL bool try_make_writable_inplace_unix ();
+
+  template <typename Type>
+  const Type* as () const
+  {
+    return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast<const Type *> (data);
+  }
+  hb_bytes_t as_bytes () const
+  { return hb_bytes_t (data, length); }
+
+  public:
+  hb_object_header_t header;
+
+  const char *data;
+  unsigned int length;
+  hb_memory_mode_t mode;
+
+  void *user_data;
+  hb_destroy_func_t destroy;
+};
+
+
+/*
+ * hb_blob_ptr_t
+ */
+
+template <typename P>
+struct hb_blob_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
+  hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
+  const T * operator -> () const { return get (); }
+  const T & operator * () const  { return *get (); }
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  const T * get () const { return b->as<T> (); }
+  hb_blob_t * get_blob () const { return b.get_raw (); }
+  unsigned int get_length () const { return b.get ()->length; }
+  void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
+
+  hb_nonnull_ptr_t<hb_blob_t> b;
+};
+
+
+#endif /* HB_BLOB_HH */
index 380f3c5..1f9e2e9 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-json.hh"
index ec9bc7c..f3abb02 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
 
index 5bca369..67f0a12 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-text.hh"
index 1d90979..6268a6c 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
 
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
deleted file mode 100644 (file)
index dd6f1dc..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011,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): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_PRIVATE_HH
-#define HB_BUFFER_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-unicode-private.hh"
-
-
-#ifndef HB_BUFFER_MAX_LEN_FACTOR
-#define HB_BUFFER_MAX_LEN_FACTOR 32
-#endif
-#ifndef HB_BUFFER_MAX_LEN_MIN
-#define HB_BUFFER_MAX_LEN_MIN 8192
-#endif
-#ifndef HB_BUFFER_MAX_LEN_DEFAULT
-#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
-#endif
-
-#ifndef HB_BUFFER_MAX_OPS_FACTOR
-#define HB_BUFFER_MAX_OPS_FACTOR 64
-#endif
-#ifndef HB_BUFFER_MAX_OPS_MIN
-#define HB_BUFFER_MAX_OPS_MIN 1024
-#endif
-#ifndef HB_BUFFER_MAX_OPS_DEFAULT
-#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
-#endif
-
-static_assert ((sizeof (hb_glyph_info_t) == 20), "");
-static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
-
-HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
-
-enum hb_buffer_scratch_flags_t {
-  HB_BUFFER_SCRATCH_FLAG_DEFAULT                       = 0x00000000u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                 = 0x00000001u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES                = 0x00000002u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK            = 0x00000004u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT           = 0x00000008u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK           = 0x00000010u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                       = 0x00000020u,
-
-  /* Reserved for complex shapers' internal use. */
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                      = 0x01000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                      = 0x02000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                      = 0x04000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                      = 0x08000000u,
-};
-HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
-
-
-/*
- * hb_buffer_t
- */
-
-struct hb_buffer_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode; /* Unicode functions */
-  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
-  hb_buffer_cluster_level_t cluster_level;
-  hb_codepoint_t replacement; /* U+FFFD or something else. */
-  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
-  unsigned int max_len; /* Maximum allowed len. */
-  int max_ops; /* Maximum allowed operations. */
-
-  /* Buffer contents */
-  hb_buffer_content_type_t content_type;
-  hb_segment_properties_t props; /* Script, language, direction */
-
-  bool successful; /* Allocations successful */
-  bool have_output; /* Whether we have an output buffer going on */
-  bool have_positions; /* Whether we have positions */
-
-  unsigned int idx; /* Cursor into ->info and ->pos arrays */
-  unsigned int len; /* Length of ->info and ->pos arrays */
-  unsigned int out_len; /* Length of ->out array if have_output */
-
-  unsigned int allocated; /* Length of allocated arrays */
-  hb_glyph_info_t     *info;
-  hb_glyph_info_t     *out_info;
-  hb_glyph_position_t *pos;
-
-  unsigned int serial;
-
-  /* Text before / after the main buffer contents.
-   * Always in Unicode, and ordered outward.
-   * Index 0 is for "pre-context", 1 for "post-context". */
-  static const unsigned int CONTEXT_LENGTH = 5;
-  hb_codepoint_t context[2][CONTEXT_LENGTH];
-  unsigned int context_len[2];
-
-  /* Debugging API */
-  hb_buffer_message_func_t message_func;
-  void *message_data;
-  hb_destroy_func_t message_destroy;
-
-  /* Internal debugging. */
-  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-#ifndef HB_NDEBUG
-  uint8_t allocated_var_bits;
-#endif
-
-
-  /* Methods */
-
-  inline void allocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (0 == (allocated_var_bits & bits));
-    allocated_var_bits |= bits;
-#endif
-  }
-  inline void deallocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-    allocated_var_bits &= ~bits;
-#endif
-  }
-  inline void assert_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-#endif
-  }
-  inline void deallocate_var_all (void)
-  {
-#ifndef HB_NDEBUG
-    allocated_var_bits = 0;
-#endif
-  }
-
-  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
-  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
-
-  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
-  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
-
-  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
-  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
-
-  inline bool has_separate_output (void) const { return info != out_info; }
-
-
-  HB_INTERNAL void reset (void);
-  HB_INTERNAL void clear (void);
-
-  inline unsigned int backtrack_len (void) const
-  { return have_output? out_len : idx; }
-  inline unsigned int lookahead_len (void) const
-  { return len - idx; }
-  inline unsigned int next_serial (void) { return serial++; }
-
-  HB_INTERNAL void add (hb_codepoint_t  codepoint,
-                       unsigned int    cluster);
-  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
-
-  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
-  HB_INTERNAL void reverse (void);
-  HB_INTERNAL void reverse_clusters (void);
-  HB_INTERNAL void guess_segment_properties (void);
-
-  HB_INTERNAL void swap_buffers (void);
-  HB_INTERNAL void remove_output (void);
-  HB_INTERNAL void clear_output (void);
-  HB_INTERNAL void clear_positions (void);
-
-  HB_INTERNAL void replace_glyphs (unsigned int num_in,
-                                  unsigned int num_out,
-                                  const hb_codepoint_t *glyph_data);
-
-  HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
-  /* Makes a copy of the glyph at idx to output and replace glyph_index */
-  HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
-  HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
-  /* Copies glyph at idx to output but doesn't advance idx */
-  HB_INTERNAL void copy_glyph (void);
-  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
-  /* Copies glyph at idx to output and advance idx.
-   * If there's no output, just advance idx. */
-  inline void
-  next_glyph (void)
-  {
-    if (have_output)
-    {
-      if (unlikely (out_info != info || out_len != idx)) {
-       if (unlikely (!make_room_for (1, 1))) return;
-       out_info[out_len] = info[idx];
-      }
-      out_len++;
-    }
-
-    idx++;
-  }
-
-  /* Advance idx without copying to output. */
-  inline void skip_glyph (void) { idx++; }
-
-  inline void reset_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask = mask;
-  }
-  inline void add_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask |= mask;
-  }
-  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
-                             unsigned int cluster_start, unsigned int cluster_end);
-
-  inline void merge_clusters (unsigned int start, unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    merge_clusters_impl (start, end);
-  }
-  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
-  /* Merge clusters for deleting current glyph, and skip it. */
-  HB_INTERNAL void delete_glyph (void);
-
-  inline void unsafe_to_break (unsigned int start,
-                              unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    unsafe_to_break_impl (start, end);
-  }
-  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
-
-
-  /* Internal methods */
-  HB_INTERNAL bool enlarge (unsigned int size);
-
-  inline bool ensure (unsigned int size)
-  { return likely (!size || size < allocated) ? true : enlarge (size); }
-
-  inline bool ensure_inplace (unsigned int size)
-  { return likely (!size || size < allocated); }
-
-  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
-  HB_INTERNAL bool shift_forward (unsigned int count);
-
-  typedef long scratch_buffer_t;
-  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
-
-  inline void clear_context (unsigned int side) { context_len[side] = 0; }
-
-  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
-
-  inline bool messaging (void) { return unlikely (message_func); }
-  inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
-  {
-    if (!messaging ())
-      return true;
-    va_list ap;
-    va_start (ap, fmt);
-    bool ret = message_impl (font, fmt, ap);
-    va_end (ap);
-    return ret;
-  }
-  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
-
-  static inline void
-  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
-  {
-    if (inf.cluster != cluster)
-    {
-      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
-       inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      else
-       inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-    }
-    inf.cluster = cluster;
-  }
-
-  inline int
-  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
-                                    unsigned int start, unsigned int end,
-                                    unsigned int cluster) const
-  {
-    for (unsigned int i = start; i < end; i++)
-      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
-    return cluster;
-  }
-  inline void
-  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
-                            unsigned int start, unsigned int end,
-                            unsigned int cluster)
-  {
-    for (unsigned int i = start; i < end; i++)
-      if (cluster != infos[i].cluster)
-      {
-       scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
-       infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      }
-  }
-
-  inline void
-  unsafe_to_break_all (void)
-  {
-    unsafe_to_break_impl (0, len);
-  }
-  inline void
-  safe_to_break_all (void)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-  }
-};
-
-
-/* Loop over clusters. Duplicated in foreach_syllable(). */
-#define foreach_cluster(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_cluster (buffer, start))
-
-static inline unsigned int
-_next_cluster (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int cluster = info[start].cluster;
-  while (++start < count && cluster == info[start].cluster)
-    ;
-
-  return start;
-}
-
-
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
-  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
-          sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var)         HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var)       HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var)           HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
-
-
-#endif /* HB_BUFFER_PRIVATE_HH */
index 1147194..6e265e8 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
+#include "hb-buffer.hh"
 
 
 static const char *serialize_formats[] = {
@@ -44,7 +44,7 @@ static const char *serialize_formats[] = {
  * Since: 0.9.7
  **/
 const char **
-hb_buffer_serialize_list_formats (void)
+hb_buffer_serialize_list_formats ()
 {
   return serialize_formats;
 }
@@ -58,7 +58,7 @@ hb_buffer_serialize_list_formats (void)
  * @str is a valid buffer serialization format, use
  * hb_buffer_serialize_list_formats() to get the list of supported formats.
  *
- * Return value: 
+ * Return value:
  * The parsed #hb_buffer_serialize_format_t.
  *
  * Since: 0.9.7
@@ -246,7 +246,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
     {
-      if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
+      if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
        p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
     }
 
@@ -319,7 +319,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
  * ## json
  * TODO.
  *
- * Return value: 
+ * Return value:
  * The number of serialized items.
  *
  * Since: 0.9.7
@@ -425,14 +425,14 @@ parse_int (const char *pp, const char *end, int32_t *pv)
  * hb_buffer_deserialize_glyphs:
  * @buffer: an #hb_buffer_t buffer.
  * @buf: (array length=buf_len):
- * @buf_len: 
+ * @buf_len:
  * @end_ptr: (out):
- * @font: 
- * @format: 
+ * @font:
+ * @format:
+ *
  *
- * 
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.7
  **/
@@ -440,8 +440,8 @@ hb_bool_t
 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
                              const char *buf,
                              int buf_len, /* -1 means nul-terminated */
-                             const char **end_ptr, /* May be nullptr */
-                             hb_font_t *font, /* May be nullptr */
+                             const char **end_ptr, /* May be NULL */
+                             hb_font_t *font, /* May be NULL */
                              hb_buffer_serialize_format_t format)
 {
   const char *end;
index 7b95aea..2dc02e9 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
-#include "hb-utf-private.hh"
+#include "hb-buffer.hh"
+#include "hb-utf.hh"
 
 
 /**
  * SECTION: hb-buffer
- * @title: Buffers
+ * @title: hb-buffer
  * @short_description: Input and output buffers
  * @include: hb.h
  *
  * Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
+ * passed to hb_shape(), and after shaping they hold the output glyphs.
  **/
 
+
 /**
  * hb_segment_properties_equal:
  * @a: first #hb_segment_properties_t to compare.
@@ -124,14 +125,14 @@ hb_buffer_t::enlarge (unsigned int size)
   hb_glyph_info_t *new_info = nullptr;
   bool separate_out = out_info != info;
 
-  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (size, sizeof (info[0]))))
     goto done;
 
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
   static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
     goto done;
 
   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
@@ -182,7 +183,11 @@ hb_buffer_t::shift_forward (unsigned int count)
   if (idx + count > len)
   {
     /* Under memory failure we might expose this area.  At least
-     * clean it up.  Oh well... */
+     * clean it up.  Oh well...
+     *
+     * Ideally, we should at least set Default_Ignorable bits on
+     * these, as well as consistent cluster values.  But the former
+     * is layering violation... */
     memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
   }
   len += count;
@@ -210,23 +215,24 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size)
 /* HarfBuzz-Internal API */
 
 void
-hb_buffer_t::reset (void)
+hb_buffer_t::reset ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_unicode_funcs_destroy (unicode);
-  unicode = hb_unicode_funcs_get_default ();
+  unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
   flags = HB_BUFFER_FLAG_DEFAULT;
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+  invisible = 0;
 
   clear ();
 }
 
 void
-hb_buffer_t::clear (void)
+hb_buffer_t::clear ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
@@ -281,9 +287,9 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
 
 
 void
-hb_buffer_t::remove_output (void)
+hb_buffer_t::remove_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -294,9 +300,9 @@ hb_buffer_t::remove_output (void)
 }
 
 void
-hb_buffer_t::clear_output (void)
+hb_buffer_t::clear_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = true;
@@ -307,9 +313,9 @@ hb_buffer_t::clear_output (void)
 }
 
 void
-hb_buffer_t::clear_positions (void)
+hb_buffer_t::clear_positions ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -322,7 +328,7 @@ hb_buffer_t::clear_positions (void)
 }
 
 void
-hb_buffer_t::swap_buffers (void)
+hb_buffer_t::swap_buffers ()
 {
   if (unlikely (!successful)) return;
 
@@ -354,6 +360,8 @@ hb_buffer_t::replace_glyphs (unsigned int num_in,
 {
   if (unlikely (!make_room_for (num_in, num_out))) return;
 
+  assert (idx + num_in <= len);
+
   merge_clusters (idx, idx + num_in);
 
   hb_glyph_info_t orig_info = info[idx];
@@ -369,37 +377,6 @@ hb_buffer_t::replace_glyphs (unsigned int num_in,
   out_len += num_out;
 }
 
-void
-hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-  out_info[out_len].codepoint = glyph_index;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = glyph_info;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::copy_glyph (void)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-
-  out_len++;
-}
-
 bool
 hb_buffer_t::move_to (unsigned int i)
 {
@@ -429,8 +406,14 @@ hb_buffer_t::move_to (unsigned int i)
     unsigned int count = out_len - i;
 
     /* This will blow in our face if memory allocation fails later
-     * in this same lookup... */
-    if (unlikely (idx < count && !shift_forward (count + 32))) return false;
+     * in this same lookup...
+     *
+     * We used to shift with extra 32 items, instead of the 0 below.
+     * But that would leave empty slots in the buffer in case of allocation
+     * failures.  Setting to zero for now to avoid other problems (see
+     * comments in shift_forward().  This can cause O(N^2) behavior more
+     * severely than adding 32 empty slots can... */
+    if (unlikely (idx < count && !shift_forward (count + 0))) return false;
 
     assert (idx >= count);
 
@@ -442,19 +425,6 @@ hb_buffer_t::move_to (unsigned int i)
   return true;
 }
 
-void
-hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1))) return;
-    out_info[out_len] = info[idx];
-  }
-  out_info[out_len].codepoint = glyph_index;
-
-  idx++;
-  out_len++;
-}
-
 
 void
 hb_buffer_t::set_masks (hb_mask_t    value,
@@ -510,7 +480,7 @@ hb_buffer_t::reverse_range (unsigned int start,
 }
 
 void
-hb_buffer_t::reverse (void)
+hb_buffer_t::reverse ()
 {
   if (unlikely (!len))
     return;
@@ -519,7 +489,7 @@ hb_buffer_t::reverse (void)
 }
 
 void
-hb_buffer_t::reverse_clusters (void)
+hb_buffer_t::reverse_clusters ()
 {
   unsigned int i, start, count, last_cluster;
 
@@ -666,7 +636,7 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
 }
 
 void
-hb_buffer_t::guess_segment_properties (void)
+hb_buffer_t::guess_segment_properties ()
 {
   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
          (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
@@ -701,6 +671,29 @@ hb_buffer_t::guess_segment_properties (void)
 
 /* Public API */
 
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+  HB_BUFFER_FLAG_DEFAULT,
+  HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+  HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+  0, /* invisible */
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+  HB_BUFFER_MAX_LEN_DEFAULT,
+  HB_BUFFER_MAX_OPS_DEFAULT,
+
+  HB_BUFFER_CONTENT_TYPE_INVALID,
+  HB_SEGMENT_PROPERTIES_DEFAULT,
+  false, /* successful */
+  true, /* have_output */
+  true  /* have_positions */
+
+  /* Zero is good enough for everything else. */
+};
+
+
 /**
  * hb_buffer_create: (Xconstructor)
  *
@@ -716,7 +709,7 @@ hb_buffer_t::guess_segment_properties (void)
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_create (void)
+hb_buffer_create ()
 {
   hb_buffer_t *buffer;
 
@@ -734,36 +727,16 @@ hb_buffer_create (void)
 /**
  * hb_buffer_get_empty:
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_get_empty (void)
+hb_buffer_get_empty ()
 {
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    false, /* successful */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+  return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
 }
 
 /**
@@ -812,14 +785,14 @@ hb_buffer_destroy (hb_buffer_t *buffer)
 /**
  * hb_buffer_set_user_data: (skip)
  * @buffer: an #hb_buffer_t.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -836,11 +809,11 @@ hb_buffer_set_user_data (hb_buffer_t        *buffer,
 /**
  * hb_buffer_get_user_data: (skip)
  * @buffer: an #hb_buffer_t.
- * @key: 
+ * @key:
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -890,9 +863,9 @@ hb_buffer_get_content_type (hb_buffer_t *buffer)
 /**
  * hb_buffer_set_unicode_funcs:
  * @buffer: an #hb_buffer_t.
- * @unicode_funcs: 
+ * @unicode_funcs:
+ *
  *
- * 
  *
  * Since: 0.9.2
  **/
@@ -900,13 +873,12 @@ void
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
                             hb_unicode_funcs_t *unicode_funcs)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (!unicode_funcs)
     unicode_funcs = hb_unicode_funcs_get_default ();
 
-
   hb_unicode_funcs_reference (unicode_funcs);
   hb_unicode_funcs_destroy (buffer->unicode);
   buffer->unicode = unicode_funcs;
@@ -916,9 +888,9 @@ hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
  * hb_buffer_get_unicode_funcs:
  * @buffer: an #hb_buffer_t.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -948,7 +920,7 @@ hb_buffer_set_direction (hb_buffer_t    *buffer,
                         hb_direction_t  direction)
 
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.direction = direction;
@@ -992,7 +964,7 @@ void
 hb_buffer_set_script (hb_buffer_t *buffer,
                      hb_script_t  script)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.script = script;
@@ -1027,7 +999,7 @@ hb_buffer_get_script (hb_buffer_t *buffer)
  * are orthogonal to the scripts, and though they are related, they are
  * different concepts and should not be confused with each other.
  *
- * Use hb_language_from_string() to convert from ISO 639 language codes to
+ * Use hb_language_from_string() to convert from BCP 47 language tags to
  * #hb_language_t.
  *
  * Since: 0.9.2
@@ -1036,7 +1008,7 @@ void
 hb_buffer_set_language (hb_buffer_t   *buffer,
                        hb_language_t  language)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.language = language;
@@ -1074,7 +1046,7 @@ void
 hb_buffer_set_segment_properties (hb_buffer_t *buffer,
                                  const hb_segment_properties_t *props)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props = *props;
@@ -1110,7 +1082,7 @@ void
 hb_buffer_set_flags (hb_buffer_t       *buffer,
                     hb_buffer_flags_t  flags)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->flags = flags;
@@ -1122,7 +1094,7 @@ hb_buffer_set_flags (hb_buffer_t       *buffer,
  *
  * See hb_buffer_set_flags().
  *
- * Return value: 
+ * Return value:
  * The @buffer flags.
  *
  * Since: 0.9.7
@@ -1136,9 +1108,9 @@ hb_buffer_get_flags (hb_buffer_t *buffer)
 /**
  * hb_buffer_set_cluster_level:
  * @buffer: an #hb_buffer_t.
- * @cluster_level: 
+ * @cluster_level:
+ *
  *
- * 
  *
  * Since: 0.9.42
  **/
@@ -1146,7 +1118,7 @@ void
 hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
                     hb_buffer_cluster_level_t  cluster_level)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->cluster_level = cluster_level;
@@ -1156,9 +1128,9 @@ hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
  * hb_buffer_get_cluster_level:
  * @buffer: an #hb_buffer_t.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.42
  **/
@@ -1185,7 +1157,7 @@ void
 hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
                                     hb_codepoint_t  replacement)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->replacement = replacement;
@@ -1197,7 +1169,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
  *
  * See hb_buffer_set_replacement_codepoint().
  *
- * Return value: 
+ * Return value:
  * The @buffer replacement #hb_codepoint_t.
  *
  * Since: 0.9.31
@@ -1210,6 +1182,46 @@ hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer)
 
 
 /**
+ * hb_buffer_set_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ * @invisible: the invisible #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces invisible characters in
+ * the shaping result.  If set to zero (default), the glyph for the
+ * U+0020 SPACE character is used.  Otherwise, this value is used
+ * verbatim.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                              hb_codepoint_t  invisible)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->invisible = invisible;
+}
+
+/**
+ * hb_buffer_get_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ *
+ * See hb_buffer_set_invisible_glyph().
+ *
+ * Return value:
+ * The @buffer invisible #hb_codepoint_t.
+ *
+ * Since: 2.0.0
+ **/
+hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer)
+{
+  return buffer->invisible;
+}
+
+
+/**
  * hb_buffer_reset:
  * @buffer: an #hb_buffer_t.
  *
@@ -1308,7 +1320,7 @@ hb_buffer_add (hb_buffer_t    *buffer,
  * Similar to hb_buffer_pre_allocate(), but clears any new items added at the
  * end.
  *
- * Return value: 
+ * Return value:
  * %true if @buffer memory allocation succeeded, %false otherwise.
  *
  * Since: 0.9.2
@@ -1317,7 +1329,7 @@ hb_bool_t
 hb_buffer_set_length (hb_buffer_t  *buffer,
                      unsigned int  length)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return length == 0;
 
   if (!buffer->ensure (length))
@@ -1498,6 +1510,8 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
  * it will be set to the process's default language as returned by
  * hb_language_get_default().  This may change in the future by
  * taking buffer script into consideration when choosing a language.
+ * Note that hb_language_get_default() is NOT threadsafe the first time
+ * it is called.  See documentation for that function for details.
  *
  * Since: 0.9.7
  **/
@@ -1521,7 +1535,7 @@ hb_buffer_add_utf (hb_buffer_t  *buffer,
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
          (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (text_length == -1)
@@ -1652,7 +1666,7 @@ hb_buffer_add_utf32 (hb_buffer_t    *buffer,
                     unsigned int    item_offset,
                     int             item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
@@ -1713,7 +1727,7 @@ hb_buffer_add_codepoints (hb_buffer_t          *buffer,
                          unsigned int          item_offset,
                          int                   item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 
@@ -1886,6 +1900,10 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
 
 /**
  * hb_buffer_diff:
+ * @buffer: a buffer.
+ * @reference: other buffer to compare to.
+ * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
+ * @position_fuzz: allowed absolute difference in position values.
  *
  * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
  * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned.  This should be used by most
@@ -1982,7 +2000,7 @@ hb_buffer_diff (hb_buffer_t *buffer,
  * @user_data:
  * @destroy:
  *
- * 
+ *
  *
  * Since: 1.1.3
  **/
index 8a2d3e8..f989d25 100644 (file)
@@ -44,7 +44,6 @@ HB_BEGIN_DECLS
  * hb_glyph_info_t:
  * @codepoint: either a Unicode code point (before shaping) or a glyph index
  *             (after shaping).
- * @mask: 
  * @cluster: the index of the character in the original text that corresponds
  *           to this #hb_glyph_info_t, or whatever the client passes to
  *           hb_buffer_add(). More than one #hb_glyph_info_t can have the same
@@ -59,11 +58,13 @@ HB_BEGIN_DECLS
  *
  * The #hb_glyph_info_t is the structure that holds information about the
  * glyphs and their relation to input text.
- *
  */
-typedef struct hb_glyph_info_t {
+typedef struct hb_glyph_info_t
+{
   hb_codepoint_t codepoint;
-  hb_mask_t      mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
+  /*< private >*/
+  hb_mask_t      mask;
+  /*< public >*/
   uint32_t       cluster;
 
   /*< private >*/
@@ -88,6 +89,9 @@ typedef struct hb_glyph_info_t {
  *                                of each line after line-breaking, or limiting
  *                                the reshaping to a small piece around the
  *                                breaking point only.
+ * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
+ *
+ * Since: 1.5.0
  */
 typedef enum { /*< flags >*/
   HB_GLYPH_FLAG_UNSAFE_TO_BREAK                = 0x00000001,
@@ -298,7 +302,15 @@ hb_buffer_set_flags (hb_buffer_t       *buffer,
 HB_EXTERN hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer);
 
-/*
+/**
+ * hb_buffer_cluster_level_t:
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into
+ *   monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
+ * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
+ *   equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
+ *
  * Since: 0.9.42
  */
 typedef enum {
@@ -332,6 +344,13 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
 HB_EXTERN hb_codepoint_t
 hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
 
+HB_EXTERN void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                              hb_codepoint_t  invisible);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer);
+
 
 HB_EXTERN void
 hb_buffer_reset (hb_buffer_t *buffer);
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
new file mode 100644 (file)
index 0000000..330f88b
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 1998-2004  David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
+ * Copyright © 2011,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): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_HH
+#define HB_BUFFER_HH
+
+#include "hb.hh"
+#include "hb-unicode.hh"
+
+
+#ifndef HB_BUFFER_MAX_LEN_FACTOR
+#define HB_BUFFER_MAX_LEN_FACTOR 32
+#endif
+#ifndef HB_BUFFER_MAX_LEN_MIN
+#define HB_BUFFER_MAX_LEN_MIN 8192
+#endif
+#ifndef HB_BUFFER_MAX_LEN_DEFAULT
+#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
+#endif
+
+#ifndef HB_BUFFER_MAX_OPS_FACTOR
+#define HB_BUFFER_MAX_OPS_FACTOR 64
+#endif
+#ifndef HB_BUFFER_MAX_OPS_MIN
+#define HB_BUFFER_MAX_OPS_MIN 1024
+#endif
+#ifndef HB_BUFFER_MAX_OPS_DEFAULT
+#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
+#endif
+
+static_assert ((sizeof (hb_glyph_info_t) == 20), "");
+static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
+
+HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
+
+enum hb_buffer_scratch_flags_t {
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT                       = 0x00000000u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                 = 0x00000001u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES                = 0x00000002u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK            = 0x00000004u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT           = 0x00000008u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK           = 0x00000010u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                       = 0x00000020u,
+
+  /* Reserved for complex shapers' internal use. */
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                      = 0x01000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                      = 0x02000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                      = 0x04000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                      = 0x08000000u,
+};
+HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
+
+
+/*
+ * hb_buffer_t
+ */
+
+struct hb_buffer_t
+{
+  hb_object_header_t header;
+
+  /* Information about how the text in the buffer should be treated */
+  hb_unicode_funcs_t *unicode; /* Unicode functions */
+  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+  hb_buffer_cluster_level_t cluster_level;
+  hb_codepoint_t replacement; /* U+FFFD or something else. */
+  hb_codepoint_t invisible; /* 0 or something else. */
+  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
+  unsigned int max_len; /* Maximum allowed len. */
+  int max_ops; /* Maximum allowed operations. */
+
+  /* Buffer contents */
+  hb_buffer_content_type_t content_type;
+  hb_segment_properties_t props; /* Script, language, direction */
+
+  bool successful; /* Allocations successful */
+  bool have_output; /* Whether we have an output buffer going on */
+  bool have_positions; /* Whether we have positions */
+
+  unsigned int idx; /* Cursor into ->info and ->pos arrays */
+  unsigned int len; /* Length of ->info and ->pos arrays */
+  unsigned int out_len; /* Length of ->out array if have_output */
+
+  unsigned int allocated; /* Length of allocated arrays */
+  hb_glyph_info_t     *info;
+  hb_glyph_info_t     *out_info;
+  hb_glyph_position_t *pos;
+
+  unsigned int serial;
+
+  /* Text before / after the main buffer contents.
+   * Always in Unicode, and ordered outward.
+   * Index 0 is for "pre-context", 1 for "post-context". */
+  static constexpr unsigned CONTEXT_LENGTH = 5u;
+  hb_codepoint_t context[2][CONTEXT_LENGTH];
+  unsigned int context_len[2];
+
+  /* Debugging API */
+  hb_buffer_message_func_t message_func;
+  void *message_data;
+  hb_destroy_func_t message_destroy;
+
+  /* Internal debugging. */
+  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+#ifndef HB_NDEBUG
+  uint8_t allocated_var_bits;
+#endif
+
+
+  /* Methods */
+
+  bool in_error () const { return !successful; }
+
+  void allocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (0 == (allocated_var_bits & bits));
+    allocated_var_bits |= bits;
+#endif
+  }
+  void deallocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+    allocated_var_bits &= ~bits;
+#endif
+  }
+  void assert_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+#endif
+  }
+  void deallocate_var_all ()
+  {
+#ifndef HB_NDEBUG
+    allocated_var_bits = 0;
+#endif
+  }
+
+  hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+  hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+
+  hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+  hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+
+  hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
+  hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+
+  bool has_separate_output () const { return info != out_info; }
+
+
+  HB_INTERNAL void reset ();
+  HB_INTERNAL void clear ();
+
+  unsigned int backtrack_len () const { return have_output? out_len : idx; }
+  unsigned int lookahead_len () const { return len - idx; }
+  unsigned int next_serial () { return serial++; }
+
+  HB_INTERNAL void add (hb_codepoint_t  codepoint,
+                       unsigned int    cluster);
+  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
+
+  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
+  HB_INTERNAL void reverse ();
+  HB_INTERNAL void reverse_clusters ();
+  HB_INTERNAL void guess_segment_properties ();
+
+  HB_INTERNAL void swap_buffers ();
+  HB_INTERNAL void remove_output ();
+  HB_INTERNAL void clear_output ();
+  HB_INTERNAL void clear_positions ();
+
+  HB_INTERNAL void replace_glyphs (unsigned int num_in,
+                                  unsigned int num_out,
+                                  const hb_codepoint_t *glyph_data);
+
+  void replace_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (out_info != info || out_len != idx)) {
+      if (unlikely (!make_room_for (1, 1))) return;
+      out_info[out_len] = info[idx];
+    }
+    out_info[out_len].codepoint = glyph_index;
+
+    idx++;
+    out_len++;
+  }
+  /* Makes a copy of the glyph at idx to output and replace glyph_index */
+  hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
+
+    if (unlikely (idx == len && !out_len))
+      return Crap(hb_glyph_info_t);
+
+    out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
+    out_info[out_len].codepoint = glyph_index;
+
+    out_len++;
+
+    return out_info[out_len - 1];
+  }
+  void output_info (const hb_glyph_info_t &glyph_info)
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = glyph_info;
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output but doesn't advance idx */
+  void copy_glyph ()
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = info[idx];
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyph ()
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+       if (unlikely (!make_room_for (1, 1))) return;
+       out_info[out_len] = info[idx];
+      }
+      out_len++;
+    }
+
+    idx++;
+  }
+  /* Copies n glyphs at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyphs (unsigned int n)
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+       if (unlikely (!make_room_for (n, n))) return;
+       memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
+      }
+      out_len += n;
+    }
+
+    idx += n;
+  }
+  /* Advance idx without copying to output. */
+  void skip_glyph () { idx++; }
+  void reset_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask = mask;
+  }
+  void add_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask |= mask;
+  }
+  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
+                             unsigned int cluster_start, unsigned int cluster_end);
+
+  void merge_clusters (unsigned int start, unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    merge_clusters_impl (start, end);
+  }
+  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
+  /* Merge clusters for deleting current glyph, and skip it. */
+  HB_INTERNAL void delete_glyph ();
+
+  void unsafe_to_break (unsigned int start,
+                              unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    unsafe_to_break_impl (start, end);
+  }
+  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
+
+
+  /* Internal methods */
+  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
+
+  HB_INTERNAL bool enlarge (unsigned int size);
+
+  bool ensure (unsigned int size)
+  { return likely (!size || size < allocated) ? true : enlarge (size); }
+
+  bool ensure_inplace (unsigned int size)
+  { return likely (!size || size < allocated); }
+
+  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
+  HB_INTERNAL bool shift_forward (unsigned int count);
+
+  typedef long scratch_buffer_t;
+  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
+
+  void clear_context (unsigned int side) { context_len[side] = 0; }
+
+  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
+
+  bool messaging () { return unlikely (message_func); }
+  bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
+  {
+    if (!messaging ())
+      return true;
+    va_list ap;
+    va_start (ap, fmt);
+    bool ret = message_impl (font, fmt, ap);
+    va_end (ap);
+    return ret;
+  }
+  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
+
+  static void
+  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
+  {
+    if (inf.cluster != cluster)
+    {
+      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+       inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      else
+       inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+    }
+    inf.cluster = cluster;
+  }
+
+  int
+  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
+                                    unsigned int start, unsigned int end,
+                                    unsigned int cluster) const
+  {
+    for (unsigned int i = start; i < end; i++)
+      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
+    return cluster;
+  }
+  void
+  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
+                            unsigned int start, unsigned int end,
+                            unsigned int cluster)
+  {
+    for (unsigned int i = start; i < end; i++)
+      if (cluster != infos[i].cluster)
+      {
+       scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
+       infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      }
+  }
+
+  void unsafe_to_break_all ()
+  { unsafe_to_break_impl (0, len); }
+  void safe_to_break_all ()
+  {
+    for (unsigned int i = 0; i < len; i++)
+      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+  }
+};
+DECLARE_NULL_INSTANCE (hb_buffer_t);
+
+
+/* Loop over clusters. Duplicated in foreach_syllable(). */
+#define foreach_cluster(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _next_cluster (buffer, start))
+
+static inline unsigned int
+_next_cluster (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int cluster = info[start].cluster;
+  while (++start < count && cluster == info[start].cluster)
+    ;
+
+  return start;
+}
+
+
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
+  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
+          sizeof (b->info[0].var))
+#define HB_BUFFER_ALLOCATE_VAR(b, var)         HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var)       HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var)           HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
+
+
+#endif /* HB_BUFFER_HH */
diff --git a/src/hb-cache.hh b/src/hb-cache.hh
new file mode 100644 (file)
index 0000000..bf26d96
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_CACHE_HH
+#define HB_CACHE_HH
+
+#include "hb.hh"
+
+
+/* Implements a lock-free cache for int->int functions. */
+
+template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+struct hb_cache_t
+{
+  static_assert ((key_bits >= cache_bits), "");
+  static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (hb_atomic_int_t)), "");
+  static_assert (sizeof (hb_atomic_int_t) == sizeof (unsigned int), "");
+
+  void init () { clear (); }
+  void fini () {}
+
+  void clear ()
+  {
+    for (unsigned i = 0; i < ARRAY_LENGTH (values); i++)
+      values[i].set_relaxed (-1);
+  }
+
+  bool get (unsigned int key, unsigned int *value) const
+  {
+    unsigned int k = key & ((1u<<cache_bits)-1);
+    unsigned int v = values[k].get_relaxed ();
+    if ((key_bits + value_bits - cache_bits == 8 * sizeof (hb_atomic_int_t) && v == (unsigned int) -1) ||
+       (v >> value_bits) != (key >> cache_bits))
+      return false;
+    *value = v & ((1u<<value_bits)-1);
+    return true;
+  }
+
+  bool set (unsigned int key, unsigned int value)
+  {
+    if (unlikely ((key >> key_bits) || (value >> value_bits)))
+      return false; /* Overflows */
+    unsigned int k = key & ((1u<<cache_bits)-1);
+    unsigned int v = ((key>>cache_bits)<<value_bits) | value;
+    values[k].set_relaxed (v);
+    return true;
+  }
+
+  private:
+  hb_atomic_int_t values[1u<<cache_bits];
+};
+
+typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
+typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
+
+
+#endif /* HB_CACHE_HH */
diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh
new file mode 100644 (file)
index 0000000..72e9e06
--- /dev/null
@@ -0,0 +1,725 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_COMMON_HH
+#define HB_CFF_INTERP_COMMON_HH
+
+namespace CFF {
+
+using namespace OT;
+
+typedef unsigned int op_code_t;
+
+
+/* === Dict operators === */
+
+/* One byte operators (0-31) */
+#define OpCode_version           0 /* CFF Top */
+#define OpCode_Notice            1 /* CFF Top */
+#define OpCode_FullName                  2 /* CFF Top */
+#define OpCode_FamilyName        3 /* CFF Top */
+#define OpCode_Weight            4 /* CFF Top */
+#define OpCode_FontBBox                  5 /* CFF Top */
+#define OpCode_BlueValues        6 /* CFF Private, CFF2 Private */
+#define OpCode_OtherBlues        7 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyBlues       8 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyOtherBlues          9 /* CFF Private, CFF2 Private */
+#define OpCode_StdHW            10 /* CFF Private, CFF2 Private */
+#define OpCode_StdVW            11 /* CFF Private, CFF2 Private */
+#define OpCode_escape           12 /* All. Shared with CS */
+#define OpCode_UniqueID                 13 /* CFF Top */
+#define OpCode_XUID             14 /* CFF Top */
+#define OpCode_charset          15 /* CFF Top (0) */
+#define OpCode_Encoding                 16 /* CFF Top (0) */
+#define OpCode_CharStrings      17 /* CFF Top, CFF2 Top */
+#define OpCode_Private          18 /* CFF Top, CFF2 FD */
+#define OpCode_Subrs            19 /* CFF Private, CFF2 Private */
+#define OpCode_defaultWidthX    20 /* CFF Private (0) */
+#define OpCode_nominalWidthX    21 /* CFF Private (0) */
+#define OpCode_vsindexdict      22 /* CFF2 Private/CS */
+#define OpCode_blenddict        23 /* CFF2 Private/CS */
+#define OpCode_vstore           24 /* CFF2 Top */
+#define OpCode_reserved25       25
+#define OpCode_reserved26       26
+#define OpCode_reserved27       27
+
+/* Numbers */
+#define OpCode_shortint                 28 /* 16-bit integer, All */
+#define OpCode_longintdict      29 /* 32-bit integer, All */
+#define OpCode_BCD              30 /* Real number, CFF2 Top/FD */
+#define OpCode_reserved31       31
+
+/* 1-byte integers */
+#define OpCode_OneByteIntFirst  32 /* All. beginning of the range of first byte ints */
+#define OpCode_OneByteIntLast  246 /* All. ending of the range of first byte int */
+
+/* 2-byte integers */
+#define OpCode_TwoBytePosInt0  247 /* All. first byte of two byte positive int (+108 to +1131) */
+#define OpCode_TwoBytePosInt1  248
+#define OpCode_TwoBytePosInt2  249
+#define OpCode_TwoBytePosInt3  250
+
+#define OpCode_TwoByteNegInt0  251 /* All. first byte of two byte negative int (-1131 to -108) */
+#define OpCode_TwoByteNegInt1  252
+#define OpCode_TwoByteNegInt2  253
+#define OpCode_TwoByteNegInt3  254
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_ESC_Base                256
+#define Make_OpCode_ESC(byte2) ((op_code_t)(OpCode_ESC_Base + (byte2)))
+
+inline op_code_t Unmake_OpCode_ESC (op_code_t op)  { return (op_code_t)(op - OpCode_ESC_Base); }
+inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; }
+inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; }
+
+#define OpCode_Copyright       Make_OpCode_ESC(0) /* CFF Top */
+#define OpCode_isFixedPitch    Make_OpCode_ESC(1) /* CFF Top (false) */
+#define OpCode_ItalicAngle     Make_OpCode_ESC(2) /* CFF Top (0) */
+#define OpCode_UnderlinePosition Make_OpCode_ESC(3) /* CFF Top (-100) */
+#define OpCode_UnderlineThickness Make_OpCode_ESC(4) /* CFF Top (50) */
+#define OpCode_PaintType       Make_OpCode_ESC(5) /* CFF Top (0) */
+#define OpCode_CharstringType  Make_OpCode_ESC(6) /* CFF Top (2) */
+#define OpCode_FontMatrix      Make_OpCode_ESC(7) /* CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/
+#define OpCode_StrokeWidth     Make_OpCode_ESC(8) /* CFF Top (0) */
+#define OpCode_BlueScale       Make_OpCode_ESC(9) /* CFF Private, CFF2 Private (0.039625) */
+#define OpCode_BlueShift       Make_OpCode_ESC(10) /* CFF Private, CFF2 Private (7) */
+#define OpCode_BlueFuzz                Make_OpCode_ESC(11) /* CFF Private, CFF2 Private (1) */
+#define OpCode_StemSnapH       Make_OpCode_ESC(12) /* CFF Private, CFF2 Private */
+#define OpCode_StemSnapV       Make_OpCode_ESC(13) /* CFF Private, CFF2 Private */
+#define OpCode_ForceBold       Make_OpCode_ESC(14) /* CFF Private (false) */
+#define OpCode_reservedESC15   Make_OpCode_ESC(15)
+#define OpCode_reservedESC16   Make_OpCode_ESC(16)
+#define OpCode_LanguageGroup   Make_OpCode_ESC(17) /* CFF Private, CFF2 Private (0) */
+#define OpCode_ExpansionFactor Make_OpCode_ESC(18) /* CFF Private, CFF2 Private (0.06) */
+#define OpCode_initialRandomSeed Make_OpCode_ESC(19) /* CFF Private (0) */
+#define OpCode_SyntheticBase   Make_OpCode_ESC(20) /* CFF Top */
+#define OpCode_PostScript      Make_OpCode_ESC(21) /* CFF Top */
+#define OpCode_BaseFontName    Make_OpCode_ESC(22) /* CFF Top */
+#define OpCode_BaseFontBlend   Make_OpCode_ESC(23) /* CFF Top */
+#define OpCode_reservedESC24   Make_OpCode_ESC(24)
+#define OpCode_reservedESC25   Make_OpCode_ESC(25)
+#define OpCode_reservedESC26   Make_OpCode_ESC(26)
+#define OpCode_reservedESC27   Make_OpCode_ESC(27)
+#define OpCode_reservedESC28   Make_OpCode_ESC(28)
+#define OpCode_reservedESC29   Make_OpCode_ESC(29)
+#define OpCode_ROS             Make_OpCode_ESC(30) /* CFF Top_CID */
+#define OpCode_CIDFontVersion  Make_OpCode_ESC(31) /* CFF Top_CID (0) */
+#define OpCode_CIDFontRevision Make_OpCode_ESC(32) /* CFF Top_CID (0) */
+#define OpCode_CIDFontType     Make_OpCode_ESC(33) /* CFF Top_CID (0) */
+#define OpCode_CIDCount                Make_OpCode_ESC(34) /* CFF Top_CID (8720) */
+#define OpCode_UIDBase         Make_OpCode_ESC(35) /* CFF Top_CID */
+#define OpCode_FDArray         Make_OpCode_ESC(36) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FDSelect                Make_OpCode_ESC(37) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FontName                Make_OpCode_ESC(38) /* CFF Top_CID */
+
+
+/* === CharString operators === */
+
+#define OpCode_hstem             1 /* CFF, CFF2 */
+#define OpCode_Reserved2         2
+#define OpCode_vstem             3 /* CFF, CFF2 */
+#define OpCode_vmoveto           4 /* CFF, CFF2 */
+#define OpCode_rlineto           5 /* CFF, CFF2 */
+#define OpCode_hlineto           6 /* CFF, CFF2 */
+#define OpCode_vlineto           7 /* CFF, CFF2 */
+#define OpCode_rrcurveto         8 /* CFF, CFF2 */
+#define OpCode_Reserved9         9
+#define OpCode_callsubr                 10 /* CFF, CFF2 */
+#define OpCode_return           11 /* CFF */
+//#define OpCode_escape                 12 /* CFF, CFF2 */
+#define OpCode_Reserved13       13
+#define OpCode_endchar          14 /* CFF */
+#define OpCode_vsindexcs        15 /* CFF2 */
+#define OpCode_blendcs          16 /* CFF2 */
+#define OpCode_Reserved17       17
+#define OpCode_hstemhm          18 /* CFF, CFF2 */
+#define OpCode_hintmask                 19 /* CFF, CFF2 */
+#define OpCode_cntrmask                 20 /* CFF, CFF2 */
+#define OpCode_rmoveto          21 /* CFF, CFF2 */
+#define OpCode_hmoveto          22 /* CFF, CFF2 */
+#define OpCode_vstemhm          23 /* CFF, CFF2 */
+#define OpCode_rcurveline       24 /* CFF, CFF2 */
+#define OpCode_rlinecurve       25 /* CFF, CFF2 */
+#define OpCode_vvcurveto        26 /* CFF, CFF2 */
+#define OpCode_hhcurveto        27 /* CFF, CFF2 */
+//#define OpCode_shortint       28 /* CFF, CFF2 */
+#define OpCode_callgsubr        29 /* CFF, CFF2 */
+#define OpCode_vhcurveto        30 /* CFF, CFF2 */
+#define OpCode_hvcurveto        31 /* CFF, CFF2 */
+
+#define OpCode_fixedcs         255 /* 32-bit fixed */
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_dotsection      Make_OpCode_ESC(0) /* CFF (obsoleted) */
+#define OpCode_ReservedESC1    Make_OpCode_ESC(1)
+#define OpCode_ReservedESC2    Make_OpCode_ESC(2)
+#define OpCode_and             Make_OpCode_ESC(3) /* CFF */
+#define OpCode_or              Make_OpCode_ESC(4) /* CFF */
+#define OpCode_not             Make_OpCode_ESC(5) /* CFF */
+#define OpCode_ReservedESC6    Make_OpCode_ESC(6)
+#define OpCode_ReservedESC7    Make_OpCode_ESC(7)
+#define OpCode_ReservedESC8    Make_OpCode_ESC(8)
+#define OpCode_abs             Make_OpCode_ESC(9) /* CFF */
+#define OpCode_add             Make_OpCode_ESC(10) /* CFF */
+#define OpCode_sub             Make_OpCode_ESC(11) /* CFF */
+#define OpCode_div             Make_OpCode_ESC(12) /* CFF */
+#define OpCode_ReservedESC13   Make_OpCode_ESC(13)
+#define OpCode_neg             Make_OpCode_ESC(14) /* CFF */
+#define OpCode_eq              Make_OpCode_ESC(15) /* CFF */
+#define OpCode_ReservedESC16   Make_OpCode_ESC(16)
+#define OpCode_ReservedESC17   Make_OpCode_ESC(17)
+#define OpCode_drop            Make_OpCode_ESC(18) /* CFF */
+#define OpCode_ReservedESC19   Make_OpCode_ESC(19)
+#define OpCode_put             Make_OpCode_ESC(20) /* CFF */
+#define OpCode_get             Make_OpCode_ESC(21) /* CFF */
+#define OpCode_ifelse          Make_OpCode_ESC(22) /* CFF */
+#define OpCode_random          Make_OpCode_ESC(23) /* CFF */
+#define OpCode_mul             Make_OpCode_ESC(24) /* CFF */
+//#define OpCode_reservedESC25 Make_OpCode_ESC(25)
+#define OpCode_sqrt            Make_OpCode_ESC(26) /* CFF */
+#define OpCode_dup             Make_OpCode_ESC(27) /* CFF */
+#define OpCode_exch            Make_OpCode_ESC(28) /* CFF */
+#define OpCode_index           Make_OpCode_ESC(29) /* CFF */
+#define OpCode_roll            Make_OpCode_ESC(30) /* CFF */
+#define OpCode_reservedESC31   Make_OpCode_ESC(31)
+#define OpCode_reservedESC32   Make_OpCode_ESC(32)
+#define OpCode_reservedESC33   Make_OpCode_ESC(33)
+#define OpCode_hflex           Make_OpCode_ESC(34) /* CFF, CFF2 */
+#define OpCode_flex            Make_OpCode_ESC(35) /* CFF, CFF2 */
+#define OpCode_hflex1          Make_OpCode_ESC(36) /* CFF, CFF2 */
+#define OpCode_flex1           Make_OpCode_ESC(37) /* CFF, CFF2 */
+
+
+#define OpCode_Invalid         0xFFFFu
+
+
+struct number_t
+{
+  void init () { set_real (0.0); }
+  void fini () {}
+
+  void set_int (int v)       { value = (double) v; }
+  int to_int () const        { return (int) value; }
+
+  void set_fixed (int32_t v) { value = v / 65536.0; }
+  int32_t to_fixed () const  { return (int32_t) (value * 65536.0); }
+
+  void set_real (double v)      { value = v; }
+  double to_real () const    { return value; }
+
+  int ceil () const          { return (int) ::ceil (value); }
+  int floor () const         { return (int) ::floor (value); }
+
+  bool in_int_range () const
+  { return ((double) (int16_t) to_int () == value); }
+
+  bool operator > (const number_t &n) const
+  { return value > n.to_real (); }
+
+  bool operator < (const number_t &n) const
+  { return n > *this; }
+
+  bool operator >= (const number_t &n) const
+  { return !(*this < n); }
+
+  bool operator <= (const number_t &n) const
+  { return !(*this > n); }
+
+  const number_t &operator += (const number_t &n)
+  {
+    set_real (to_real () + n.to_real ());
+
+    return *this;
+  }
+
+  protected:
+  double  value;
+};
+
+/* byte string */
+struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
+{
+  // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, int value)
+  {
+    TRACE_SERIALIZE (this);
+
+    if (unlikely ((value < minVal || value > maxVal)))
+      return_trace (false);
+
+    HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+    if (unlikely (p == nullptr)) return_trace (false);
+    p->set (intOp);
+
+    INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
+    if (unlikely (ip == nullptr)) return_trace (false);
+    ip->set ((unsigned int)value);
+
+    return_trace (true);
+  }
+
+  static bool serialize_int4 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
+
+  static bool serialize_int2 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
+
+  /* Defining null_size allows a Null object may be created. Should be safe because:
+   * A descendent struct Dict uses a Null pointer to indicate a missing table,
+   * checked before access.
+   * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
+   * checks the length before access. A Null pointer is used as the initial pointer
+   * along with zero length by the default ctor.
+   */
+  DEFINE_SIZE_MIN(0);
+};
+
+/* Holder of a section of byte string within a CFFIndex entry */
+struct byte_str_t : hb_ubytes_t
+{
+  byte_str_t ()
+    : hb_ubytes_t () {}
+  byte_str_t (const UnsizedByteStr& s, unsigned int l)
+    : hb_ubytes_t ((const unsigned char*)&s, l) {}
+  byte_str_t (const unsigned char *s, unsigned int l)
+    : hb_ubytes_t (s, l) {}
+  byte_str_t (const hb_ubytes_t &ub)   /* conversion from hb_ubytes_t */
+    : hb_ubytes_t (ub) {}
+  
+  /* sub-string */
+  byte_str_t sub_str (unsigned int offset, unsigned int len_) const
+  { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
+
+  bool check_limit (unsigned int offset, unsigned int count) const
+  { return (offset + count <= length); }
+};
+
+/* A byte string associated with the current offset and an error condition */
+struct byte_str_ref_t
+{
+  byte_str_ref_t ()
+  { init (); }
+
+  void init ()
+  {
+    str = byte_str_t ();
+    offset = 0;
+    error = false;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
+    : str (str_), offset (offset_), error (false) {}
+
+  void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+  {
+    str = str_;
+    offset = offset_;
+    error = false;
+  }
+
+  const unsigned char& operator [] (int i) {
+    if (unlikely ((unsigned int)(offset + i) >= str.length))
+    {
+      set_error ();
+      return Null(unsigned char);
+    }
+    else
+      return str[offset + i];
+  }
+
+  /* Conversion to byte_str_t */
+  operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+
+  byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
+  { return str.sub_str (offset_, len_); }
+
+  bool avail (unsigned int count=1) const
+  {
+    return (!in_error () && str.check_limit (offset, count));
+  }
+  void inc (unsigned int count=1)
+  {
+    if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
+    {
+      offset += count;
+    }
+    else
+    {
+      offset = str.length;
+      set_error ();
+    }
+  }
+
+  void set_error ()      { error = true; }
+  bool in_error () const { return error; }
+
+  byte_str_t       str;
+  unsigned int  offset; /* beginning of the sub-string within str */
+
+  protected:
+  bool   error;
+};
+
+typedef hb_vector_t<byte_str_t> byte_str_array_t;
+
+/* stack */
+template <typename ELEM, int LIMIT>
+struct stack_t
+{
+  void init ()
+  {
+    error = false;
+    count = 0;
+    elements.init ();
+    elements.resize (kSizeLimit);
+    for (unsigned int i = 0; i < elements.length; i++)
+      elements[i].init ();
+  }
+
+  void fini ()
+  {
+    elements.fini_deep ();
+  }
+
+  ELEM& operator [] (unsigned int i)
+  {
+    if (unlikely (i >= count)) set_error ();
+    return elements[i];
+  }
+
+  void push (const ELEM &v)
+  {
+    if (likely (count < elements.length))
+      elements[count++] = v;
+    else
+      set_error ();
+  }
+
+  ELEM &push ()
+  {
+    if (likely (count < elements.length))
+      return elements[count++];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  ELEM& pop ()
+  {
+    if (likely (count > 0))
+      return elements[--count];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  void pop (unsigned int n)
+  {
+    if (likely (count >= n))
+      count -= n;
+    else
+      set_error ();
+  }
+
+  const ELEM& peek ()
+  {
+    if (likely (count > 0))
+      return elements[count-1];
+    else
+    {
+      set_error ();
+      return Null(ELEM);
+    }
+  }
+
+  void unpop ()
+  {
+    if (likely (count < elements.length))
+      count++;
+    else
+      set_error ();
+  }
+
+  void clear () { count = 0; }
+
+  bool in_error () const { return (error || elements.in_error ()); }
+  void set_error ()      { error = true; }
+
+  unsigned int get_count () const { return count; }
+  bool is_empty () const { return count == 0; }
+
+  static constexpr unsigned kSizeLimit = LIMIT;
+
+  protected:
+  bool error;
+  unsigned int count;
+  hb_vector_t<ELEM> elements;
+};
+
+/* argument stack */
+template <typename ARG=number_t>
+struct arg_stack_t : stack_t<ARG, 513>
+{
+  void push_int (int v)
+  {
+    ARG &n = S::push ();
+    n.set_int (v);
+  }
+
+  void push_fixed (int32_t v)
+  {
+    ARG &n = S::push ();
+    n.set_fixed (v);
+  }
+
+  void push_real (double v)
+  {
+    ARG &n = S::push ();
+    n.set_real (v);
+  }
+
+  ARG& pop_num () { return this->pop (); }
+
+  int pop_int ()  { return this->pop ().to_int (); }
+
+  unsigned int pop_uint ()
+  {
+    int i = pop_int ();
+    if (unlikely (i < 0))
+    {
+      i = 0;
+      S::set_error ();
+    }
+    return (unsigned)i;
+  }
+
+  void push_longint_from_substr (byte_str_ref_t& str_ref)
+  {
+    push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3]));
+    str_ref.inc (4);
+  }
+
+  bool push_fixed_from_substr (byte_str_ref_t& str_ref)
+  {
+    if (unlikely (!str_ref.avail (4)))
+      return false;
+    push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]);
+    str_ref.inc (4);
+    return true;
+  }
+
+  hb_array_t<const ARG> get_subarray (unsigned int start) const
+  {
+    return S::elements.sub_array (start);
+  }
+
+  private:
+  typedef stack_t<ARG, 513> S;
+};
+
+/* an operator prefixed by its operands in a byte string */
+struct op_str_t
+{
+  void init () {}
+  void fini () {}
+
+  op_code_t  op;
+  byte_str_t str;
+};
+
+/* base of OP_SERIALIZER */
+struct op_serializer_t
+{
+  protected:
+  bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const
+  {
+    TRACE_SERIALIZE (this);
+
+    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+    if (unlikely (d == nullptr)) return_trace (false);
+    memcpy (d, &opstr.str[0], opstr.str.length);
+    return_trace (true);
+  }
+};
+
+template <typename VAL>
+struct parsed_values_t
+{
+  void init ()
+  {
+    opStart = 0;
+    values.init ();
+  }
+  void fini () { values.fini_deep (); }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
+  {
+    VAL *val = values.push ();
+    val->op = op;
+    val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
+  {
+    VAL *val = values.push (v);
+    val->op = op;
+    val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  bool has_op (op_code_t op) const
+  {
+    for (unsigned int i = 0; i < get_count (); i++)
+      if (get_value (i).op == op) return true;
+    return false;
+  }
+
+  unsigned get_count () const { return values.length; }
+  const VAL &get_value (unsigned int i) const { return values[i]; }
+  const VAL &operator [] (unsigned int i) const { return get_value (i); }
+
+  unsigned int       opStart;
+  hb_vector_t<VAL>   values;
+};
+
+template <typename ARG=number_t>
+struct interp_env_t
+{
+  void init (const byte_str_t &str_)
+  {
+    str_ref.reset (str_);
+    argStack.init ();
+    error = false;
+  }
+  void fini () { argStack.fini (); }
+
+  bool in_error () const
+  { return error || str_ref.in_error () || argStack.in_error (); }
+
+  void set_error () { error = true; }
+
+  op_code_t fetch_op ()
+  {
+    op_code_t  op = OpCode_Invalid;
+    if (unlikely (!str_ref.avail ()))
+      return OpCode_Invalid;
+    op = (op_code_t)(unsigned char)str_ref[0];
+    if (op == OpCode_escape) {
+      if (unlikely (!str_ref.avail ()))
+       return OpCode_Invalid;
+      op = Make_OpCode_ESC(str_ref[1]);
+      str_ref.inc ();
+    }
+    str_ref.inc ();
+    return op;
+  }
+
+  const ARG& eval_arg (unsigned int i)
+  {
+    return argStack[i];
+  }
+
+  ARG& pop_arg ()
+  {
+    return argStack.pop ();
+  }
+
+  void pop_n_args (unsigned int n)
+  {
+    argStack.pop (n);
+  }
+
+  void clear_args ()
+  {
+    pop_n_args (argStack.get_count ());
+  }
+
+  byte_str_ref_t    str_ref;
+  arg_stack_t<ARG> argStack;
+  protected:
+  bool   error;
+};
+
+typedef interp_env_t<> num_interp_env_t;
+
+template <typename ARG=number_t>
+struct opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<ARG>& env)
+  {
+    switch (op) {
+      case OpCode_shortint:
+       env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1]));
+       env.str_ref.inc (2);
+       break;
+
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+       env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
+       env.str_ref.inc ();
+       break;
+
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+       env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
+       env.str_ref.inc ();
+       break;
+
+      default:
+       /* 1-byte integer */
+       if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
+       {
+         env.argStack.push_int ((int)op - 139);
+       } else {
+         /* invalid unknown operator */
+         env.clear_args ();
+         env.set_error ();
+       }
+       break;
+    }
+  }
+};
+
+template <typename ENV>
+struct interpreter_t {
+
+  ~interpreter_t() { fini (); }
+
+  void fini () { env.fini (); }
+
+  ENV env;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_COMMON_HH */
diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh
new file mode 100644 (file)
index 0000000..283bdf1
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_CS_COMMON_HH
+#define HB_CFF_INTERP_CS_COMMON_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+enum cs_type_t {
+  CSType_CharString,
+  CSType_GlobalSubr,
+  CSType_LocalSubr
+};
+
+struct call_context_t
+{
+  void init (const byte_str_ref_t substr_=byte_str_ref_t (), cs_type_t type_=CSType_CharString, unsigned int subr_num_=0)
+  {
+    str_ref = substr_;
+    type = type_;
+    subr_num = subr_num_;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t  str_ref;
+  cs_type_t      type;
+  unsigned int    subr_num;
+};
+
+/* call stack */
+const unsigned int kMaxCallLimit = 10;
+struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
+
+template <typename SUBRS>
+struct biased_subrs_t
+{
+  void init (const SUBRS &subrs_)
+  {
+    subrs = &subrs_;
+    unsigned int  nSubrs = get_count ();
+    if (nSubrs < 1240)
+      bias = 107;
+    else if (nSubrs < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  void fini () {}
+
+  unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
+  unsigned int get_bias () const { return bias; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (unlikely ((subrs == nullptr) || index >= subrs->count))
+      return Null(byte_str_t);
+    else
+      return (*subrs)[index];
+  }
+
+  protected:
+  unsigned int  bias;
+  const SUBRS   *subrs;
+};
+
+struct point_t
+{
+  void init ()
+  {
+    x.init ();
+    y.init ();
+  }
+
+  void set_int (int _x, int _y)
+  {
+    x.set_int (_x);
+    y.set_int (_y);
+  }
+
+  void move_x (const number_t &dx) { x += dx; }
+  void move_y (const number_t &dy) { y += dy; }
+  void move (const number_t &dx, const number_t &dy) { move_x (dx); move_y (dy); }
+  void move (const point_t &d) { move_x (d.x); move_y (d.y); }
+
+  number_t  x;
+  number_t  y;
+};
+
+template <typename ARG, typename SUBRS>
+struct cs_interp_env_t : interp_env_t<ARG>
+{
+  void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_)
+  {
+    interp_env_t<ARG>::init (str);
+
+    context.init (str, CSType_CharString);
+    seen_moveto = true;
+    seen_hintmask = false;
+    hstem_count = 0;
+    vstem_count = 0;
+    hintmask_size = 0;
+    pt.init ();
+    callStack.init ();
+    globalSubrs.init (globalSubrs_);
+    localSubrs.init (localSubrs_);
+  }
+  void fini ()
+  {
+    interp_env_t<ARG>::fini ();
+
+    callStack.fini ();
+    globalSubrs.fini ();
+    localSubrs.fini ();
+  }
+
+  bool in_error () const
+  {
+    return callStack.in_error () || SUPER::in_error ();
+  }
+
+  bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
+  {
+    int n = SUPER::argStack.pop_int ();
+    n += biasedSubrs.get_bias ();
+    if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
+      return false;
+
+    subr_num = (unsigned int)n;
+    return true;
+  }
+
+  void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
+  {
+    unsigned int subr_num;
+
+    if (unlikely (!popSubrNum (biasedSubrs, subr_num)
+                || callStack.get_count () >= kMaxCallLimit))
+    {
+      SUPER::set_error ();
+      return;
+    }
+    context.str_ref = SUPER::str_ref;
+    callStack.push (context);
+
+    context.init ( biasedSubrs[subr_num], type, subr_num);
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void returnFromSubr ()
+  {
+    if (unlikely (SUPER::str_ref.in_error ()))
+      SUPER::set_error ();
+    context = callStack.pop ();
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void determine_hintmask_size ()
+  {
+    if (!seen_hintmask)
+    {
+      vstem_count += SUPER::argStack.get_count() / 2;
+      hintmask_size = (hstem_count + vstem_count + 7) >> 3;
+      seen_hintmask = true;
+    }
+  }
+
+  void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; }
+  bool is_endchar () const { return endchar_flag; }
+
+  const number_t &get_x () const { return pt.x; }
+  const number_t &get_y () const { return pt.y; }
+  const point_t &get_pt () const { return pt; }
+
+  void moveto (const point_t &pt_ ) { pt = pt_; }
+
+  public:
+  call_context_t   context;
+  bool   endchar_flag;
+  bool   seen_moveto;
+  bool   seen_hintmask;
+
+  unsigned int  hstem_count;
+  unsigned int  vstem_count;
+  unsigned int  hintmask_size;
+  call_stack_t callStack;
+  biased_subrs_t<SUBRS>   globalSubrs;
+  biased_subrs_t<SUBRS>   localSubrs;
+
+  private:
+  point_t       pt;
+
+  typedef interp_env_t<ARG> SUPER;
+};
+
+template <typename ENV, typename PARAM>
+struct path_procs_null_t
+{
+  static void rmoveto (ENV &env, PARAM& param) {}
+  static void hmoveto (ENV &env, PARAM& param) {}
+  static void vmoveto (ENV &env, PARAM& param) {}
+  static void rlineto (ENV &env, PARAM& param) {}
+  static void hlineto (ENV &env, PARAM& param) {}
+  static void vlineto (ENV &env, PARAM& param) {}
+  static void rrcurveto (ENV &env, PARAM& param) {}
+  static void rcurveline (ENV &env, PARAM& param) {}
+  static void rlinecurve (ENV &env, PARAM& param) {}
+  static void vvcurveto (ENV &env, PARAM& param) {}
+  static void hhcurveto (ENV &env, PARAM& param) {}
+  static void vhcurveto (ENV &env, PARAM& param) {}
+  static void hvcurveto (ENV &env, PARAM& param) {}
+  static void moveto (ENV &env, PARAM& param, const point_t &pt) {}
+  static void line (ENV &env, PARAM& param, const point_t &pt1) {}
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {}
+  static void hflex (ENV &env, PARAM& param) {}
+  static void flex (ENV &env, PARAM& param) {}
+  static void hflex1 (ENV &env, PARAM& param) {}
+  static void flex1 (ENV &env, PARAM& param) {}
+};
+
+template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
+struct cs_opset_t : opset_t<ARG>
+{
+  static void process_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+       env.returnFromSubr ();
+       break;
+      case OpCode_endchar:
+       OPSET::check_width (op, env, param);
+       env.set_endchar (true);
+       OPSET::flush_args_and_op (op, env, param);
+       break;
+
+      case OpCode_fixedcs:
+       env.argStack.push_fixed_from_substr (env.str_ref);
+       break;
+
+      case OpCode_callsubr:
+       env.callSubr (env.localSubrs, CSType_LocalSubr);
+       break;
+
+      case OpCode_callgsubr:
+       env.callSubr (env.globalSubrs, CSType_GlobalSubr);
+       break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+       OPSET::check_width (op, env, param);
+       OPSET::process_hstem (op, env, param);
+       break;
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+       OPSET::check_width (op, env, param);
+       OPSET::process_vstem (op, env, param);
+       break;
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+       OPSET::check_width (op, env, param);
+       OPSET::process_hintmask (op, env, param);
+       break;
+      case OpCode_rmoveto:
+       OPSET::check_width (op, env, param);
+       PATH::rmoveto (env, param);
+       OPSET::process_post_move (op, env, param);
+       break;
+      case OpCode_hmoveto:
+       OPSET::check_width (op, env, param);
+       PATH::hmoveto (env, param);
+       OPSET::process_post_move (op, env, param);
+       break;
+      case OpCode_vmoveto:
+       OPSET::check_width (op, env, param);
+       PATH::vmoveto (env, param);
+       OPSET::process_post_move (op, env, param);
+       break;
+      case OpCode_rlineto:
+       PATH::rlineto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_hlineto:
+       PATH::hlineto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_vlineto:
+       PATH::vlineto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_rrcurveto:
+       PATH::rrcurveto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_rcurveline:
+       PATH::rcurveline (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_rlinecurve:
+       PATH::rlinecurve (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_vvcurveto:
+       PATH::vvcurveto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_hhcurveto:
+       PATH::hhcurveto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_vhcurveto:
+       PATH::vhcurveto (env, param);
+       process_post_path (op, env, param);
+       break;
+      case OpCode_hvcurveto:
+       PATH::hvcurveto (env, param);
+       process_post_path (op, env, param);
+       break;
+
+      case OpCode_hflex:
+       PATH::hflex (env, param);
+       OPSET::process_post_flex (op, env, param);
+       break;
+
+      case OpCode_flex:
+       PATH::flex (env, param);
+       OPSET::process_post_flex (op, env, param);
+       break;
+
+      case OpCode_hflex1:
+       PATH::hflex1 (env, param);
+       OPSET::process_post_flex (op, env, param);
+       break;
+
+      case OpCode_flex1:
+       PATH::flex1 (env, param);
+       OPSET::process_post_flex (op, env, param);
+       break;
+
+      default:
+       SUPER::process_op (op, env);
+       break;
+    }
+  }
+
+  static void process_hstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.hstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_vstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.vstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.determine_hintmask_size ();
+    if (likely (env.str_ref.avail (env.hintmask_size)))
+    {
+      OPSET::flush_hintmask (op, env, param);
+      env.str_ref.inc (env.hintmask_size);
+    }
+  }
+
+  static void process_post_flex (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void check_width (op_code_t op, ENV &env, PARAM& param)
+  {}
+
+  static void process_post_move (op_code_t op, ENV &env, PARAM& param)
+  {
+    if (!env.seen_moveto)
+    {
+      env.determine_hintmask_size ();
+      env.seen_moveto = true;
+    }
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_post_path (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void flush_args_and_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args (env, param);
+    OPSET::flush_op (op, env, param);
+  }
+
+  static void flush_args (ENV &env, PARAM& param)
+  {
+    env.pop_n_args (env.argStack.get_count ());
+  }
+
+  static void flush_op (op_code_t op, ENV &env, PARAM& param)
+  {
+  }
+
+  static void flush_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static bool is_number_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_shortint:
+      case OpCode_fixedcs:
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+       return true;
+
+      default:
+       /* 1-byte integer */
+       return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast);
+    }
+  }
+
+  protected:
+  typedef opset_t<ARG>  SUPER;
+};
+
+template <typename PATH, typename ENV, typename PARAM>
+struct path_procs_t
+{
+  static void rmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    const number_t &dy = env.pop_arg ();
+    const number_t &dx = env.pop_arg ();
+    pt1.move (dx, dy);
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void hmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_x (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void vmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_y (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void rlineto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void hlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_y (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void vlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_x (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rrcurveto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void rcurveline (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rlinecurve (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    unsigned int line_limit = (env.argStack.get_count () % 6);
+    for (; i + 2 <= line_limit; i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void vvcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_x (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void hhcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_y (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void vhcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+       PATH::curve (env, param, pt1, pt2, pt3);
+       pt1 = env.get_pt ();
+       pt1.move_x (env.eval_arg (i));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+       pt3 = pt2;
+       pt3.move_y (env.eval_arg (i+3));
+       PATH::curve (env, param, pt1, pt2, pt3);
+
+       pt1 = pt3;
+       pt1.move_y (env.eval_arg (i+4));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+       pt3 = pt2;
+       pt3.move_x (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+       pt3.move_y (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+       pt1 = env.get_pt ();
+       pt1.move_y (env.eval_arg (i));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+       pt3 = pt2;
+       pt3.move_x (env.eval_arg (i+3));
+       PATH::curve (env, param, pt1, pt2, pt3);
+
+       pt1 = pt3;
+       pt1.move_x (env.eval_arg (i+4));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+       pt3 = pt2;
+       pt3.move_y (env.eval_arg (i+7));
+       if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+         pt3.move_x (env.eval_arg (i+8));
+       PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  static void hvcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+       PATH::curve (env, param, pt1, pt2, pt3);
+       pt1 = env.get_pt ();
+       pt1.move_y (env.eval_arg (i));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+       pt3 = pt2;
+       pt3.move_x (env.eval_arg (i+3));
+       PATH::curve (env, param, pt1, pt2, pt3);
+
+       pt1 = pt3;
+       pt1.move_x (env.eval_arg (i+4));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+       pt3 = pt2;
+       pt3.move_y (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+       pt3.move_x (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+       pt1 = env.get_pt ();
+       pt1.move_x (env.eval_arg (i));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+       pt3 = pt2;
+       pt3.move_y (env.eval_arg (i+3));
+       PATH::curve (env, param, pt1, pt2, pt3);
+
+       pt1 = pt3;
+       pt1.move_y (env.eval_arg (i+4));
+       pt2 = pt1;
+       pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+       pt3 = pt2;
+       pt3.move_x (env.eval_arg (i+7));
+       if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+         pt3.move_y (env.eval_arg (i+8));
+       PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  /* default actions to be overridden */
+  static void moveto (ENV &env, PARAM& param, const point_t &pt)
+  { env.moveto (pt); }
+
+  static void line (ENV &env, PARAM& param, const point_t &pt1)
+  { PATH::moveto (env, param, pt1); }
+
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  { PATH::moveto (env, param, pt3); }
+
+  static void hflex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 7))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (0));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (1), env.eval_arg (2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (3));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (4));
+      point_t pt5 = pt4;
+      pt5.move_x (env.eval_arg (5));
+      pt5.y = pt1.y;
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (6));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 13))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+      pt6.move (env.eval_arg (10), env.eval_arg (11));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void hflex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 9))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (4));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (5));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (8));
+      pt6.y = env.get_pt ().y;
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 11))
+    {
+      point_t d;
+      d.init ();
+      for (unsigned int i = 0; i < 10; i += 2)
+       d.move (env.eval_arg (i), env.eval_arg (i+1));
+
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+
+      if (fabs (d.x.to_real ()) > fabs (d.y.to_real ()))
+      {
+       pt6.move_x (env.eval_arg (10));
+       pt6.y = env.get_pt ().y;
+      }
+      else
+      {
+       pt6.x = env.get_pt ().x;
+       pt6.move_y (env.eval_arg (10));
+      }
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  protected:
+  static void curve2 (ENV &env, PARAM& param,
+                     const point_t &pt1, const point_t &pt2, const point_t &pt3,
+                     const point_t &pt4, const point_t &pt5, const point_t &pt6)
+  {
+    PATH::curve (env, param, pt1, pt2, pt3);
+    PATH::curve (env, param, pt4, pt5, pt6);
+  }
+};
+
+template <typename ENV, typename OPSET, typename PARAM>
+struct cs_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    SUPER::env.set_endchar (false);
+
+    for (;;) {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+       return false;
+      if (SUPER::env.is_endchar ())
+       break;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_CS_COMMON_HH */
diff --git a/src/hb-cff-interp-dict-common.hh b/src/hb-cff-interp-dict-common.hh
new file mode 100644 (file)
index 0000000..2c54909
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_DICT_COMMON_HH
+#define HB_CFF_INTERP_DICT_COMMON_HH
+
+#include "hb-cff-interp-common.hh"
+#include <math.h>
+#include <float.h>
+
+namespace CFF {
+
+using namespace OT;
+
+/* an opstr and the parsed out dict value(s) */
+struct dict_val_t : op_str_t
+{
+  void init () { single_val.set_int (0); }
+  void fini () {}
+
+  number_t           single_val;
+};
+
+typedef dict_val_t num_dict_val_t;
+
+template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
+
+template <typename OPSTR=op_str_t>
+struct top_dict_values_t : dict_values_t<OPSTR>
+{
+  void init ()
+  {
+    dict_values_t<OPSTR>::init ();
+    charStringsOffset = 0;
+    FDArrayOffset = 0;
+  }
+  void fini () { dict_values_t<OPSTR>::fini (); }
+
+  unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+       return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+       return opstr.str.length;
+    }
+  }
+
+  unsigned int  charStringsOffset;
+  unsigned int  FDArrayOffset;
+};
+
+struct dict_opset_t : opset_t<number_t>
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env)
+  {
+    switch (op) {
+      case OpCode_longintdict:  /* 5-byte integer */
+       env.argStack.push_longint_from_substr (env.str_ref);
+       break;
+
+      case OpCode_BCD:  /* real number */
+       env.argStack.push_real (parse_bcd (env.str_ref));
+       break;
+
+      default:
+       opset_t<number_t>::process_op (op, env);
+       break;
+    }
+  }
+
+  static double parse_bcd (byte_str_ref_t& str_ref)
+  {
+    bool    neg = false;
+    double  int_part = 0;
+    uint64_t frac_part = 0;
+    uint32_t  frac_count = 0;
+    bool    exp_neg = false;
+    uint32_t  exp_part = 0;
+    bool    exp_overflow = false;
+    enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
+    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
+    const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
+    const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */
+
+    double  value = 0.0;
+    unsigned char byte = 0;
+    for (uint32_t i = 0;; i++)
+    {
+      char d;
+      if ((i & 1) == 0)
+      {
+       if (!str_ref.avail ())
+       {
+         str_ref.set_error ();
+         return 0.0;
+       }
+       byte = str_ref[0];
+       str_ref.inc ();
+       d = byte >> 4;
+      }
+      else
+       d = byte & 0x0F;
+
+      switch (d)
+      {
+       case RESERVED:
+         str_ref.set_error ();
+         return value;
+
+       case END:
+         value = (double)(neg? -int_part: int_part);
+         if (frac_count > 0)
+         {
+           double frac = (frac_part / pow (10.0, (double)frac_count));
+           if (neg) frac = -frac;
+           value += frac;
+         }
+         if (unlikely (exp_overflow))
+         {
+           if (value == 0.0)
+             return value;
+           if (exp_neg)
+             return neg? -DBL_MIN: DBL_MIN;
+           else
+             return neg? -DBL_MAX: DBL_MAX;
+         }
+         if (exp_part != 0)
+         {
+           if (exp_neg)
+             value /= pow (10.0, (double)exp_part);
+           else
+             value *= pow (10.0, (double)exp_part);
+         }
+         return value;
+
+       case NEG:
+         if (i != 0)
+         {
+           str_ref.set_error ();
+           return 0.0;
+         }
+         neg = true;
+         break;
+
+       case DECIMAL:
+         if (part != INT_PART)
+         {
+           str_ref.set_error ();
+           return value;
+         }
+         part = FRAC_PART;
+         break;
+
+       case EXP_NEG:
+         exp_neg = true;
+         HB_FALLTHROUGH;
+
+       case EXP_POS:
+         if (part == EXP_PART)
+         {
+           str_ref.set_error ();
+           return value;
+         }
+         part = EXP_PART;
+         break;
+
+       default:
+         switch (part) {
+           default:
+           case INT_PART:
+             int_part = (int_part * 10) + d;
+             break;
+
+           case FRAC_PART:
+             if (likely (frac_part <= MAX_FRACT / 10))
+             {
+               frac_part = (frac_part * 10) + (unsigned)d;
+               frac_count++;
+             }
+             break;
+
+           case EXP_PART:
+             if (likely (exp_part * 10 + d <= MAX_EXP))
+             {
+               exp_part = (exp_part * 10) + d;
+             }
+             else
+               exp_overflow = true;
+             break;
+         }
+      }
+    }
+
+    return value;
+  }
+
+  static bool is_hint_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+       return true;
+      default:
+       return false;
+    }
+  }
+};
+
+template <typename VAL=op_str_t>
+struct top_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
+  {
+    switch (op) {
+      case OpCode_CharStrings:
+       dictval.charStringsOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_FDArray:
+       dictval.FDArrayOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_FontMatrix:
+       env.clear_args ();
+       break;
+      default:
+       dict_opset_t::process_op (op, env);
+       break;
+    }
+  }
+};
+
+template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
+struct dict_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    param.init ();
+    while (SUPER::env.str_ref.avail ())
+    {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+       return false;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_DICT_COMMON_HH */
diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh
new file mode 100644 (file)
index 0000000..c7209ed
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF1_INTERP_CS_HH
+#define HB_CFF1_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+typedef biased_subrs_t<CFF1Subrs>   cff1_biased_subrs_t;
+
+struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+    processed_width = false;
+    has_width = false;
+    arg_start = 0;
+    in_seac = false;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  void set_width (bool has_width_)
+  {
+    if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
+    {
+      if (has_width_)
+      {
+       width = SUPER::argStack[0];
+       has_width = true;
+       arg_start = 1;
+      }
+    }
+    processed_width = true;
+  }
+
+  void clear_args ()
+  {
+    arg_start = 0;
+    SUPER::clear_args ();
+  }
+
+  void set_in_seac (bool _in_seac) { in_seac = _in_seac; }
+
+  bool   processed_width;
+  bool   has_width;
+  unsigned int  arg_start;
+  number_t     width;
+  bool   in_seac;
+
+  private:
+  typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
+};
+
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
+struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
+{
+  /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
+  /* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */
+
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_dotsection:
+       SUPER::flush_args_and_op (op, env, param);
+       break;
+
+      case OpCode_endchar:
+       OPSET::check_width (op, env, param);
+       if (env.argStack.get_count () >= 4)
+       {
+         OPSET::process_seac (env, param);
+       }
+       OPSET::flush_args_and_op (op, env, param);
+       env.set_endchar (true);
+       break;
+
+      default:
+       SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void check_width (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    if (!env.processed_width)
+    {
+      bool  has_width = false;
+      switch (op)
+      {
+       case OpCode_endchar:
+       case OpCode_hstem:
+       case OpCode_hstemhm:
+       case OpCode_vstem:
+       case OpCode_vstemhm:
+       case OpCode_hintmask:
+       case OpCode_cntrmask:
+         has_width = ((env.argStack.get_count () & 1) != 0);
+         break;
+       case OpCode_hmoveto:
+       case OpCode_vmoveto:
+         has_width = (env.argStack.get_count () > 1);
+         break;
+       case OpCode_rmoveto:
+         has_width = (env.argStack.get_count () > 2);
+         break;
+       default:
+         return;
+      }
+      env.set_width (has_width);
+    }
+  }
+
+  static void process_seac (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+  }
+
+  static void flush_args (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    SUPER::flush_args (env, param);
+    env.clear_args ();  /* pop off width */
+  }
+
+  private:
+  typedef cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF1_INTERP_CS_HH */
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
new file mode 100644 (file)
index 0000000..49e5ee7
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF2_INTERP_CS_HH
+#define HB_CFF2_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+struct blend_arg_t : number_t
+{
+  void init ()
+  {
+    number_t::init ();
+    deltas.init ();
+  }
+
+  void fini ()
+  {
+    number_t::fini ();
+    deltas.fini_deep ();
+  }
+
+  void set_int (int v) { reset_blends (); number_t::set_int (v); }
+  void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
+  void set_real (double v) { reset_blends (); number_t::set_real (v); }
+
+  void set_blends (unsigned int numValues_, unsigned int valueIndex_,
+                         unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+  {
+    numValues = numValues_;
+    valueIndex = valueIndex_;
+    deltas.resize (numBlends);
+    for (unsigned int i = 0; i < numBlends; i++)
+      deltas[i] = blends_[i];
+  }
+
+  bool blending () const { return deltas.length > 0; }
+  void reset_blends ()
+  {
+    numValues = valueIndex = 0;
+    deltas.resize (0);
+  }
+
+  unsigned int numValues;
+  unsigned int valueIndex;
+  hb_vector_t<number_t> deltas;
+};
+
+typedef interp_env_t<blend_arg_t> BlendInterpEnv;
+typedef biased_subrs_t<CFF2Subrs>   cff2_biased_subrs_t;
+
+struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd,
+                   const int *coords_=nullptr, unsigned int num_coords_=0)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+
+    coords = coords_;
+    num_coords = num_coords_;
+    varStore = acc.varStore;
+    seen_blend = false;
+    seen_vsindex_ = false;
+    scalars.init ();
+    do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
+    set_ivs (acc.privateDicts[fd].ivs);
+  }
+
+  void fini ()
+  {
+    scalars.fini ();
+    SUPER::fini ();
+  }
+
+  op_code_t fetch_op ()
+  {
+    if (this->str_ref.avail ())
+      return SUPER::fetch_op ();
+
+    /* make up return or endchar op */
+    if (this->callStack.is_empty ())
+      return OpCode_endchar;
+    else
+      return OpCode_return;
+  }
+
+  const blend_arg_t& eval_arg (unsigned int i)
+  {
+    blend_arg_t  &arg = argStack[i];
+    blend_arg (arg);
+    return arg;
+  }
+
+  const blend_arg_t& pop_arg ()
+  {
+    blend_arg_t  &arg = argStack.pop ();
+    blend_arg (arg);
+    return arg;
+  }
+
+  void process_blend ()
+  {
+    if (!seen_blend)
+    {
+      region_count = varStore->varStore.get_region_index_count (get_ivs ());
+      if (do_blend)
+      {
+       scalars.resize (region_count);
+       varStore->varStore.get_scalars (get_ivs (),
+                                       (int *)coords, num_coords,
+                                       &scalars[0], region_count);
+      }
+      seen_blend = true;
+    }
+  }
+
+  void process_vsindex ()
+  {
+    unsigned int  index = argStack.pop_uint ();
+    if (unlikely (seen_vsindex () || seen_blend))
+    {
+      set_error ();
+    }
+    else
+    {
+      set_ivs (index);
+    }
+    seen_vsindex_ = true;
+  }
+
+  unsigned int get_region_count () const { return region_count; }
+  void  set_region_count (unsigned int region_count_) { region_count = region_count_; }
+  unsigned int get_ivs () const { return ivs; }
+  void  set_ivs (unsigned int ivs_) { ivs = ivs_; }
+  bool  seen_vsindex () const { return seen_vsindex_; }
+
+  protected:
+  void blend_arg (blend_arg_t &arg)
+  {
+    if (do_blend && arg.blending ())
+    {
+      if (likely (scalars.length == arg.deltas.length))
+      {
+       double v = arg.to_real ();
+       for (unsigned int i = 0; i < scalars.length; i++)
+       {
+         v += (double)scalars[i] * arg.deltas[i].to_real ();
+       }
+       arg.set_real (v);
+       arg.deltas.resize (0);
+      }
+    }
+  }
+
+  protected:
+  const int     *coords;
+  unsigned int  num_coords;
+  const         CFF2VariationStore *varStore;
+  unsigned int  region_count;
+  unsigned int  ivs;
+  hb_vector_t<float>  scalars;
+  bool   do_blend;
+  bool   seen_vsindex_;
+  bool   seen_blend;
+
+  typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+};
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
+struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_callsubr:
+      case OpCode_callgsubr:
+       /* a subroutine number shoudln't be a blended value */
+       if (unlikely (env.argStack.peek ().blending ()))
+       {
+         env.set_error ();
+         break;
+       }
+       SUPER::process_op (op, env, param);
+       break;
+
+      case OpCode_blendcs:
+       OPSET::process_blend (env, param);
+       break;
+
+      case OpCode_vsindexcs:
+       if (unlikely (env.argStack.peek ().blending ()))
+       {
+         env.set_error ();
+         break;
+       }
+       OPSET::process_vsindex (env, param);
+       break;
+
+      default:
+       SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    unsigned int n, k;
+
+    env.process_blend ();
+    k = env.get_region_count ();
+    n = env.argStack.pop_uint ();
+    /* copy the blend values into blend array of the default values */
+    unsigned int start = env.argStack.get_count () - ((k+1) * n);
+    /* let an obvious error case fail, but note CFF2 spec doesn't forbid n==0 */
+    if (unlikely (start > env.argStack.get_count ()))
+    {
+      env.set_error ();
+      return;
+    }
+    for (unsigned int i = 0; i < n; i++)
+    {
+      const hb_array_t<const blend_arg_t>      blends = env.argStack.get_subarray (start + n + (i * k));
+      env.argStack[start + i].set_blends (n, i, k, blends);
+    }
+
+    /* pop off blend values leaving default values now adorned with blend values */
+    env.argStack.pop (k * n);
+  }
+
+  static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    env.process_vsindex ();
+    env.clear_args ();
+  }
+
+  private:
+  typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF2_INTERP_CS_HH */
index a67fcf8..93f5b79 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-mutex-private.hh"
-#include "hb-object-private.hh"
+#include "hb-machinery.hh"
 
 #include <locale.h>
 #ifdef HAVE_XLOCALE_H
 #endif
 
 
+/**
+ * SECTION:hb-common
+ * @title: hb-common
+ * @short_description: Common data types
+ * @include: hb.h
+ *
+ * Common data types used across HarfBuzz are defined here.
+ **/
+
+
 /* hb_options_t */
 
-hb_options_union_t _hb_options;
+hb_atomic_int_t _hb_options;
 
 void
-_hb_options_init (void)
+_hb_options_init ()
 {
   hb_options_union_t u;
   u.i = 0;
-  u.opts.initialized = 1;
+  u.opts.initialized = true;
+
+  const char *c = getenv ("HB_OPTIONS");
+  if (c)
+  {
+    while (*c)
+    {
+      const char *p = strchr (c, ':');
+      if (!p)
+        p = c + strlen (c);
+
+#define OPTION(name, symbol) \
+       if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
+
+      OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
+      OPTION ("aat", aat);
+
+#undef OPTION
 
-  char *c = getenv ("HB_OPTIONS");
-  u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
+      c = *p ? p + 1 : p;
+    }
+
+  }
 
   /* This is idempotent and threadsafe. */
-  _hb_options = u;
+  _hb_options.set_relaxed (u.i);
 }
 
 
@@ -176,7 +204,7 @@ static const char canon_map[256] = {
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
-  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
@@ -219,11 +247,10 @@ struct hb_language_item_t {
   struct hb_language_item_t *next;
   hb_language_t lang;
 
-  inline bool operator == (const char *s) const {
-    return lang_equal (lang, s);
-  }
+  bool operator == (const char *s) const
+  { return lang_equal (lang, s); }
 
-  inline hb_language_item_t & operator = (const char *s) {
+  hb_language_item_t & operator = (const char *s) {
     /* If a custom allocated is used calling strdup() pairs
     badly with a call to the custom free() in fini() below.
     Therefore don't call strdup(), implement its behavior.
@@ -240,21 +267,21 @@ struct hb_language_item_t {
     return *this;
   }
 
-  void fini (void) { free ((void *) lang); }
+  void fini () { free ((void *) lang); }
 };
 
 
 /* Thread-safe lock-free language list */
 
-static hb_language_item_t *langs;
+static hb_atomic_ptr_t <hb_language_item_t> langs;
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
 static void
-free_langs (void)
+free_langs ()
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr))
+  hb_language_item_t *first_lang = langs;
+  if (unlikely (!langs.cmpexch (first_lang, nullptr)))
     goto retry;
 
   while (first_lang) {
@@ -270,7 +297,7 @@ static hb_language_item_t *
 lang_find_or_insert (const char *key)
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
+  hb_language_item_t *first_lang = langs;
 
   for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
     if (*lang == key)
@@ -288,13 +315,14 @@ retry:
     return nullptr;
   }
 
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+  if (unlikely (!langs.cmpexch (first_lang, lang)))
+  {
     lang->fini ();
     free (lang);
     goto retry;
   }
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
   if (!first_lang)
     atexit (free_langs); /* First person registers atexit() callback. */
 #endif
@@ -306,14 +334,14 @@ retry:
 /**
  * hb_language_from_string:
  * @str: (array length=len) (element-type uint8_t): a string representing
- *       ISO 639 language code
+ *       a BCP 47 language tag
  * @len: length of the @str, or -1 if it is %NULL-terminated.
  *
- * Converts @str representing an ISO 639 language code to the corresponding
+ * Converts @str representing a BCP 47 language tag to the corresponding
  * #hb_language_t.
  *
  * Return value: (transfer none):
- * The #hb_language_t corresponding to the ISO 639 language code.
+ * The #hb_language_t corresponding to the BCP 47 language tag.
  *
  * Since: 0.9.2
  **/
@@ -361,24 +389,32 @@ hb_language_to_string (hb_language_t language)
 /**
  * hb_language_get_default:
  *
+ * Get default language from current locale.
  *
+ * Note that the first time this function is called, it calls
+ * "setlocale (LC_CTYPE, nullptr)" to fetch current locale.  The underlying
+ * setlocale function is, in many implementations, NOT threadsafe.  To avoid
+ * problems, call this function once before multiple threads can call it.
+ * This function is only used from hb_buffer_guess_segment_properties() by
+ * HarfBuzz itself.
  *
  * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 hb_language_t
-hb_language_get_default (void)
+hb_language_get_default ()
 {
-  static hb_language_t default_language = HB_LANGUAGE_INVALID;
+  static hb_atomic_ptr_t <hb_language_t> default_language;
 
-  hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
-  if (unlikely (language == HB_LANGUAGE_INVALID)) {
+  hb_language_t language = default_language;
+  if (unlikely (language == HB_LANGUAGE_INVALID))
+  {
     language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
-    (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+    (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
   }
 
-  return default_language;
+  return language;
 }
 
 
@@ -530,7 +566,6 @@ hb_script_get_horizontal_direction (hb_script_t script)
 
     /* Unicode-8.0 additions */
     case HB_SCRIPT_HATRAN:
-    case HB_SCRIPT_OLD_HUNGARIAN:
 
     /* Unicode-9.0 additions */
     case HB_SCRIPT_ADLAM:
@@ -544,7 +579,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
 
 
     /* https://github.com/harfbuzz/harfbuzz/issues/1000 */
+    case HB_SCRIPT_OLD_HUNGARIAN:
     case HB_SCRIPT_OLD_ITALIC:
+    case HB_SCRIPT_RUNIC:
 
       return HB_DIRECTION_INVALID;
   }
@@ -587,6 +624,19 @@ hb_user_data_array_t::get (hb_user_data_key_t *key)
 
 /* hb_version */
 
+
+/**
+ * SECTION:hb-version
+ * @title: hb-version
+ * @short_description: Information about the version of HarfBuzz in use
+ * @include: hb.h
+ *
+ * These functions and macros allow accessing version of the HarfBuzz
+ * library used at compile- as well as run-time, and to direct code
+ * conditionally based on those versions, again, at compile- or run-time.
+ **/
+
+
 /**
  * hb_version:
  * @major: (out): Library major version component.
@@ -617,7 +667,7 @@ hb_version (unsigned int *major,
  * Since: 0.9.2
  **/
 const char *
-hb_version_string (void)
+hb_version_string ()
 {
   return HB_VERSION_STRING;
 }
@@ -729,48 +779,48 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
 
 #ifdef USE_XLOCALE
 
-static HB_LOCALE_T C_locale;
-
-#ifdef HB_USE_ATEXIT
-static void
-free_C_locale (void)
-{
-retry:
-  HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
-  if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr))
-    goto retry;
-
-  if (locale)
-    HB_FREE_LOCALE (locale);
-}
+#if HB_USE_ATEXIT
+static void free_static_C_locale ();
 #endif
 
-static HB_LOCALE_T
-get_C_locale (void)
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
+                                                         hb_C_locale_lazy_loader_t>
 {
-retry:
-  HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
-  if (unlikely (!C))
+  static HB_LOCALE_T create ()
   {
-    C = HB_CREATE_LOCALE ("C");
-
-    if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
-    {
-      HB_FREE_LOCALE (C_locale);
-      goto retry;
-    }
+    HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_C_locale); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+    atexit (free_static_C_locale);
 #endif
+
+    return C_locale;
+  }
+  static void destroy (HB_LOCALE_T p)
+  {
+    HB_FREE_LOCALE (p);
   }
+  static HB_LOCALE_T get_null ()
+  {
+    return nullptr;
+  }
+} static_C_locale;
 
-  return C;
+#if HB_USE_ATEXIT
+static
+void free_static_C_locale ()
+{
+  static_C_locale.free_instance ();
 }
 #endif
 
+static HB_LOCALE_T
+get_C_locale ()
+{
+  return static_C_locale.get_unconst ();
+}
+#endif /* USE_XLOCALE */
+
 static bool
 parse_float (const char **pp, const char *end, float *pv)
 {
@@ -846,7 +896,7 @@ parse_tag (const char **pp, const char *end, hb_tag_t *tag)
   }
 
   const char *p = *pp;
-  while (*pp < end && ISALNUM(**pp))
+  while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
     (*pp)++;
 
   if (p == *pp || *pp - p > 4)
@@ -875,15 +925,15 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
 
   bool has_start;
 
-  feature->start = 0;
-  feature->end = (unsigned int) -1;
+  feature->start = HB_FEATURE_GLOBAL_START;
+  feature->end = HB_FEATURE_GLOBAL_END;
 
   if (!parse_char (pp, end, '['))
     return true;
 
   has_start = parse_uint (pp, end, &feature->start);
 
-  if (parse_char (pp, end, ':')) {
+  if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) {
     parse_uint (pp, end, &feature->end);
   } else {
     if (has_start)
@@ -1063,10 +1113,19 @@ hb_variation_to_string (hb_variation_t *variation,
   while (len && s[len - 1] == ' ')
     len--;
   s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
+  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
 
   assert (len < ARRAY_LENGTH (s));
   len = MIN (len, size - 1);
   memcpy (buf, s, len);
   buf[len] = '\0';
 }
+
+/* If there is no visibility control, then hb-static.cc will NOT
+ * define anything.  Instead, we get it to define one set in here
+ * only, so only libharfbuzz.so defines them, not other libs. */
+#ifdef HB_NO_VISIBILITY
+#undef HB_NO_VISIBILITY
+#include "hb-static.cc"
+#define HB_NO_VISIBILITY 1
+#endif
index 5dc1ebc..2b29e44 100644 (file)
 #ifndef HB_COMMON_H
 #define HB_COMMON_H
 
+#ifndef HB_EXTERN
+#define HB_EXTERN extern
+#endif
+
 #ifndef HB_BEGIN_DECLS
 # ifdef __cplusplus
 #  define HB_BEGIN_DECLS       extern "C" {
@@ -63,6 +67,23 @@ typedef unsigned __int64 uint64_t;
 #  include <stdint.h>
 #endif
 
+#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define HB_DEPRECATED __attribute__((__deprecated__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+#define HB_DEPRECATED __declspec(deprecated)
+#else
+#define HB_DEPRECATED
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define HB_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
+#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
+#define HB_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
+#else
+#define HB_DEPRECATED_FOR(f) HB_DEPRECATED
+#endif
+
+
 HB_BEGIN_DECLS
 
 
@@ -86,8 +107,8 @@ typedef union _hb_var_int_t {
 
 typedef uint32_t hb_tag_t;
 
-#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
-#define HB_UNTAG(tag)   ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
+#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
+#define HB_UNTAG(tag)   (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
 
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
@@ -340,13 +361,15 @@ typedef enum
   HB_SCRIPT_INVALID                            = HB_TAG_NONE,
 
   /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
-   * without risking undefined behavior.  Include both a signed and unsigned max,
-   * since technically enums are int, and indeed, hb_script_t ends up being signed.
+   * without risking undefined behavior.  We have two, for historical reasons.
+   * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
+   * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
+   *
    * See this thread for technicalities:
    *
    *   https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
    */
-  _HB_SCRIPT_MAX_VALUE                         = HB_TAG_MAX, /*< skip >*/
+  _HB_SCRIPT_MAX_VALUE                         = HB_TAG_MAX_SIGNED, /*< skip >*/
   _HB_SCRIPT_MAX_VALUE_SIGNED                  = HB_TAG_MAX_SIGNED /*< skip >*/
 
 } hb_script_t;
@@ -379,6 +402,19 @@ typedef void (*hb_destroy_func_t) (void *user_data);
 
 /* Font features and variations. */
 
+/**
+ * HB_FEATURE_GLOBAL_START
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_START        0
+/**
+ * HB_FEATURE_GLOBAL_END
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_END  ((unsigned int) -1)
+
 typedef struct hb_feature_t {
   hb_tag_t      tag;
   uint32_t      value;
@@ -412,6 +448,50 @@ HB_EXTERN void
 hb_variation_to_string (hb_variation_t *variation,
                        char *buf, unsigned int size);
 
+/**
+ * hb_color_t:
+ *
+ * Data type for holding color values.
+ *
+ * Since: 2.1.0
+ */
+typedef uint32_t hb_color_t;
+
+#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
+
+/**
+ * hb_color_get_alpha:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_alpha(color)      ((color) & 0xFF)
+/**
+ * hb_color_get_red:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_red(color)                (((color) >> 8) & 0xFF)
+/**
+ * hb_color_get_green:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_green(color)      (((color) >> 16) & 0xFF)
+/**
+ * hb_color_get_blue:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_blue(color)       (((color) >> 24) & 0xFF)
+
 
 HB_END_DECLS
 
index 61f9c35..42ea3ea 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER coretext
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
 
 #include "hb-coretext.h"
+#include "hb-aat-layout.hh"
 #include <math.h>
 
+
+/**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
@@ -91,13 +99,8 @@ _hb_cg_font_release (void *data)
 }
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
-       fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
-)
-
 static CTFontDescriptorRef
-get_last_resort_font_desc (void)
+get_last_resort_font_desc ()
 {
   // TODO Handle allocation failures?
   CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
@@ -211,7 +214,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
   }
 
   CFURLRef original_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
   ATSFontRef atsFont;
   FSRef fsref;
   OSStatus status;
@@ -241,7 +244,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
        * process in Blink. This can be detected by the new file URL location
        * that the newly found font points to. */
       CFURLRef new_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
       atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
       status = ATSFontGetFileReference (atsFont, &fsref);
       if (status == noErr)
@@ -270,7 +273,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
   return ct_font;
 }
 
-hb_coretext_shaper_face_data_t *
+hb_coretext_face_data_t *
 _hb_coretext_shaper_face_data_create (hb_face_t *face)
 {
   CGFontRef cg_font = create_cg_font (face);
@@ -281,11 +284,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
     return nullptr;
   }
 
-  return (hb_coretext_shaper_face_data_t *) cg_font;
+  return (hb_coretext_face_data_t *) cg_font;
 }
 
 void
-_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
+_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
 {
   CFRelease ((CGFontRef) data);
 }
@@ -302,17 +305,17 @@ hb_coretext_face_create (CGFontRef cg_font)
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  return (CGFontRef) HB_SHAPER_DATA_GET (face);
+  return (CGFontRef) (const void *) face->data.coretext;
 }
 
 
-hb_coretext_shaper_font_data_t *
+hb_coretext_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   hb_face_t *face = font->face;
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
+  const hb_coretext_face_data_t *face_data = face->data.coretext;
+  if (unlikely (!face_data)) return nullptr;
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
 
@@ -322,15 +325,47 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
     return nullptr;
   }
 
-  return (hb_coretext_shaper_font_data_t *) ct_font;
+  return (hb_coretext_font_data_t *) ct_font;
 }
 
 void
-_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
+_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
 {
   CFRelease ((CTFontRef) data);
 }
 
+static const hb_coretext_font_data_t *
+hb_coretext_font_data_sync (hb_font_t *font)
+{
+retry:
+  const hb_coretext_font_data_t *data = font->data.coretext;
+  if (unlikely (!data)) return nullptr;
+
+  if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+  {
+    /* XXX-MT-bug
+     * Note that evaluating condition above can be dangerous if another thread
+     * got here first and destructed data.  That's, as always, bad use pattern.
+     * If you modify the font (change font size), other threads must not be
+     * using it at the same time.  However, since this check is delayed to
+     * when one actually tries to shape something, this is a XXX race condition
+     * (and the only one we have that I know of) right now.  Ie. you modify the
+     * font size in one thread, then (supposedly safely) try to use it from two
+     * or more threads and BOOM!  I'm not sure how to fix this.  We want RCU.
+     */
+
+    /* Drop and recreate. */
+    /* If someone dropped it in the mean time, throw it away and don't touch it.
+     * Otherwise, destruct it. */
+    if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
+      _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
+    else
+      goto retry;
+  }
+  return font->data.coretext;
+}
+
+
 /*
  * Since: 1.7.2
  */
@@ -343,13 +378,13 @@ hb_coretext_font_create (CTFontRef ct_font)
   hb_font_t *font = hb_font_create (face);
   hb_face_destroy (face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
 
   /* Let there be dragons here... */
-  HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
+  font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
 
   return font;
 }
@@ -357,31 +392,8 @@ hb_coretext_font_create (CTFontRef ct_font)
 CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font)
 {
-  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef) HB_SHAPER_DATA_GET (font);
-}
-
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_shaper_shape_plan_data_t {};
-
-hb_coretext_shaper_shape_plan_data_t *
-_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
-{
+  const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
+  return data ? (CTFontRef) data : nullptr;
 }
 
 
@@ -432,183 +444,6 @@ struct range_record_t {
 };
 
 
-/* The following enum members are added in OS X 10.8. */
-#define kAltHalfWidthTextSelector              6
-#define kAltProportionalTextSelector           5
-#define kAlternateHorizKanaOffSelector         1
-#define kAlternateHorizKanaOnSelector          0
-#define kAlternateKanaType                     34
-#define kAlternateVertKanaOffSelector          3
-#define kAlternateVertKanaOnSelector           2
-#define kCaseSensitiveLayoutOffSelector                1
-#define kCaseSensitiveLayoutOnSelector         0
-#define kCaseSensitiveLayoutType               33
-#define kCaseSensitiveSpacingOffSelector       3
-#define kCaseSensitiveSpacingOnSelector                2
-#define kContextualAlternatesOffSelector       1
-#define kContextualAlternatesOnSelector                0
-#define kContextualAlternatesType              36
-#define kContextualLigaturesOffSelector                19
-#define kContextualLigaturesOnSelector         18
-#define kContextualSwashAlternatesOffSelector  5
-#define kContextualSwashAlternatesOnSelector   4
-#define kDefaultLowerCaseSelector              0
-#define kDefaultUpperCaseSelector              0
-#define kHistoricalLigaturesOffSelector                21
-#define kHistoricalLigaturesOnSelector         20
-#define kHojoCharactersSelector                        12
-#define kJIS2004CharactersSelector             11
-#define kLowerCasePetiteCapsSelector           2
-#define kLowerCaseSmallCapsSelector            1
-#define kLowerCaseType                         37
-#define kMathematicalGreekOffSelector          11
-#define kMathematicalGreekOnSelector           10
-#define kNLCCharactersSelector                 13
-#define kQuarterWidthTextSelector              4
-#define kScientificInferiorsSelector           4
-#define kStylisticAltEightOffSelector          17
-#define kStylisticAltEightOnSelector           16
-#define kStylisticAltEighteenOffSelector       37
-#define kStylisticAltEighteenOnSelector                36
-#define kStylisticAltElevenOffSelector         23
-#define kStylisticAltElevenOnSelector          22
-#define kStylisticAltFifteenOffSelector                31
-#define kStylisticAltFifteenOnSelector         30
-#define kStylisticAltFiveOffSelector           11
-#define kStylisticAltFiveOnSelector            10
-#define kStylisticAltFourOffSelector           9
-#define kStylisticAltFourOnSelector            8
-#define kStylisticAltFourteenOffSelector       29
-#define kStylisticAltFourteenOnSelector                28
-#define kStylisticAltNineOffSelector           19
-#define kStylisticAltNineOnSelector            18
-#define kStylisticAltNineteenOffSelector       39
-#define kStylisticAltNineteenOnSelector                38
-#define kStylisticAltOneOffSelector            3
-#define kStylisticAltOneOnSelector             2
-#define kStylisticAltSevenOffSelector          15
-#define kStylisticAltSevenOnSelector           14
-#define kStylisticAltSeventeenOffSelector      35
-#define kStylisticAltSeventeenOnSelector       34
-#define kStylisticAltSixOffSelector            13
-#define kStylisticAltSixOnSelector             12
-#define kStylisticAltSixteenOffSelector                33
-#define kStylisticAltSixteenOnSelector         32
-#define kStylisticAltTenOffSelector            21
-#define kStylisticAltTenOnSelector             20
-#define kStylisticAltThirteenOffSelector       27
-#define kStylisticAltThirteenOnSelector                26
-#define kStylisticAltThreeOffSelector          7
-#define kStylisticAltThreeOnSelector           6
-#define kStylisticAltTwelveOffSelector         25
-#define kStylisticAltTwelveOnSelector          24
-#define kStylisticAltTwentyOffSelector         41
-#define kStylisticAltTwentyOnSelector          40
-#define kStylisticAltTwoOffSelector            5
-#define kStylisticAltTwoOnSelector             4
-#define kStylisticAlternativesType             35
-#define kSwashAlternatesOffSelector            3
-#define kSwashAlternatesOnSelector             2
-#define kThirdWidthTextSelector                        3
-#define kTraditionalNamesCharactersSelector    14
-#define kUpperCasePetiteCapsSelector           2
-#define kUpperCaseSmallCapsSelector            1
-#define kUpperCaseType                         38
-
-/* Table data courtesy of Apple. */
-static const struct feature_mapping_t {
-    FourCharCode otFeatureTag;
-    uint16_t aatFeatureType;
-    uint16_t selectorToEnable;
-    uint16_t selectorToDisable;
-} feature_mappings[] = {
-    { 'c2pc',   kUpperCaseType,             kUpperCasePetiteCapsSelector,           kDefaultUpperCaseSelector },
-    { 'c2sc',   kUpperCaseType,             kUpperCaseSmallCapsSelector,            kDefaultUpperCaseSelector },
-    { 'calt',   kContextualAlternatesType,  kContextualAlternatesOnSelector,        kContextualAlternatesOffSelector },
-    { 'case',   kCaseSensitiveLayoutType,   kCaseSensitiveLayoutOnSelector,         kCaseSensitiveLayoutOffSelector },
-    { 'clig',   kLigaturesType,             kContextualLigaturesOnSelector,         kContextualLigaturesOffSelector },
-    { 'cpsp',   kCaseSensitiveLayoutType,   kCaseSensitiveSpacingOnSelector,        kCaseSensitiveSpacingOffSelector },
-    { 'cswh',   kContextualAlternatesType,  kContextualSwashAlternatesOnSelector,   kContextualSwashAlternatesOffSelector },
-    { 'dlig',   kLigaturesType,             kRareLigaturesOnSelector,               kRareLigaturesOffSelector },
-    { 'expt',   kCharacterShapeType,        kExpertCharactersSelector,              16 },
-    { 'frac',   kFractionsType,             kDiagonalFractionsSelector,             kNoFractionsSelector },
-    { 'fwid',   kTextSpacingType,           kMonospacedTextSelector,                7 },
-    { 'halt',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'hist',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hkna',   kAlternateKanaType,         kAlternateHorizKanaOnSelector,          kAlternateHorizKanaOffSelector, },
-    { 'hlig',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hngl',   kTransliterationType,       kHanjaToHangulSelector,                 kNoTransliterationSelector },
-    { 'hojo',   kCharacterShapeType,        kHojoCharactersSelector,                16 },
-    { 'hwid',   kTextSpacingType,           kHalfWidthTextSelector,                 7 },
-    { 'ital',   kItalicCJKRomanType,        kCJKItalicRomanOnSelector,              kCJKItalicRomanOffSelector },
-    { 'jp04',   kCharacterShapeType,        kJIS2004CharactersSelector,             16 },
-    { 'jp78',   kCharacterShapeType,        kJIS1978CharactersSelector,             16 },
-    { 'jp83',   kCharacterShapeType,        kJIS1983CharactersSelector,             16 },
-    { 'jp90',   kCharacterShapeType,        kJIS1990CharactersSelector,             16 },
-    { 'liga',   kLigaturesType,             kCommonLigaturesOnSelector,             kCommonLigaturesOffSelector },
-    { 'lnum',   kNumberCaseType,            kUpperCaseNumbersSelector,              2 },
-    { 'mgrk',   kMathematicalExtrasType,    kMathematicalGreekOnSelector,           kMathematicalGreekOffSelector },
-    { 'nlck',   kCharacterShapeType,        kNLCCharactersSelector,                 16 },
-    { 'onum',   kNumberCaseType,            kLowerCaseNumbersSelector,              2 },
-    { 'ordn',   kVerticalPositionType,      kOrdinalsSelector,                      kNormalPositionSelector },
-    { 'palt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'pcap',   kLowerCaseType,             kLowerCasePetiteCapsSelector,           kDefaultLowerCaseSelector },
-    { 'pkna',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'pnum',   kNumberSpacingType,         kProportionalNumbersSelector,           4 },
-    { 'pwid',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'qwid',   kTextSpacingType,           kQuarterWidthTextSelector,              7 },
-    { 'ruby',   kRubyKanaType,              kRubyKanaOnSelector,                    kRubyKanaOffSelector },
-    { 'sinf',   kVerticalPositionType,      kScientificInferiorsSelector,           kNormalPositionSelector },
-    { 'smcp',   kLowerCaseType,             kLowerCaseSmallCapsSelector,            kDefaultLowerCaseSelector },
-    { 'smpl',   kCharacterShapeType,        kSimplifiedCharactersSelector,          16 },
-    { 'ss01',   kStylisticAlternativesType, kStylisticAltOneOnSelector,             kStylisticAltOneOffSelector },
-    { 'ss02',   kStylisticAlternativesType, kStylisticAltTwoOnSelector,             kStylisticAltTwoOffSelector },
-    { 'ss03',   kStylisticAlternativesType, kStylisticAltThreeOnSelector,           kStylisticAltThreeOffSelector },
-    { 'ss04',   kStylisticAlternativesType, kStylisticAltFourOnSelector,            kStylisticAltFourOffSelector },
-    { 'ss05',   kStylisticAlternativesType, kStylisticAltFiveOnSelector,            kStylisticAltFiveOffSelector },
-    { 'ss06',   kStylisticAlternativesType, kStylisticAltSixOnSelector,             kStylisticAltSixOffSelector },
-    { 'ss07',   kStylisticAlternativesType, kStylisticAltSevenOnSelector,           kStylisticAltSevenOffSelector },
-    { 'ss08',   kStylisticAlternativesType, kStylisticAltEightOnSelector,           kStylisticAltEightOffSelector },
-    { 'ss09',   kStylisticAlternativesType, kStylisticAltNineOnSelector,            kStylisticAltNineOffSelector },
-    { 'ss10',   kStylisticAlternativesType, kStylisticAltTenOnSelector,             kStylisticAltTenOffSelector },
-    { 'ss11',   kStylisticAlternativesType, kStylisticAltElevenOnSelector,          kStylisticAltElevenOffSelector },
-    { 'ss12',   kStylisticAlternativesType, kStylisticAltTwelveOnSelector,          kStylisticAltTwelveOffSelector },
-    { 'ss13',   kStylisticAlternativesType, kStylisticAltThirteenOnSelector,        kStylisticAltThirteenOffSelector },
-    { 'ss14',   kStylisticAlternativesType, kStylisticAltFourteenOnSelector,        kStylisticAltFourteenOffSelector },
-    { 'ss15',   kStylisticAlternativesType, kStylisticAltFifteenOnSelector,         kStylisticAltFifteenOffSelector },
-    { 'ss16',   kStylisticAlternativesType, kStylisticAltSixteenOnSelector,         kStylisticAltSixteenOffSelector },
-    { 'ss17',   kStylisticAlternativesType, kStylisticAltSeventeenOnSelector,       kStylisticAltSeventeenOffSelector },
-    { 'ss18',   kStylisticAlternativesType, kStylisticAltEighteenOnSelector,        kStylisticAltEighteenOffSelector },
-    { 'ss19',   kStylisticAlternativesType, kStylisticAltNineteenOnSelector,        kStylisticAltNineteenOffSelector },
-    { 'ss20',   kStylisticAlternativesType, kStylisticAltTwentyOnSelector,          kStylisticAltTwentyOffSelector },
-    { 'subs',   kVerticalPositionType,      kInferiorsSelector,                     kNormalPositionSelector },
-    { 'sups',   kVerticalPositionType,      kSuperiorsSelector,                     kNormalPositionSelector },
-    { 'swsh',   kContextualAlternatesType,  kSwashAlternatesOnSelector,             kSwashAlternatesOffSelector },
-    { 'titl',   kStyleOptionsType,          kTitlingCapsSelector,                   kNoStyleOptionsSelector },
-    { 'tnam',   kCharacterShapeType,        kTraditionalNamesCharactersSelector,    16 },
-    { 'tnum',   kNumberSpacingType,         kMonospacedNumbersSelector,             4 },
-    { 'trad',   kCharacterShapeType,        kTraditionalCharactersSelector,         16 },
-    { 'twid',   kTextSpacingType,           kThirdWidthTextSelector,                7 },
-    { 'unic',   kLetterCaseType,            14,                                     15 },
-    { 'valt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vert',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'vhal',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'vkna',   kAlternateKanaType,         kAlternateVertKanaOnSelector,           kAlternateVertKanaOffSelector },
-    { 'vpal',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vrt2',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'zero',   kTypographicExtrasType,     kSlashedZeroOnSelector,                 kSlashedZeroOffSelector },
-};
-
-static int
-_hb_feature_mapping_cmp (const void *key_, const void *entry_)
-{
-  unsigned int key = * (unsigned int *) key_;
-  const feature_mapping_t * entry = (const feature_mapping_t *) entry_;
-  return key < entry->otFeatureTag ? -1 :
-        key > entry->otFeatureTag ? 1 :
-        0;
-}
-
 hb_bool_t
 _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
                    hb_font_t          *font,
@@ -617,15 +452,15 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
+  CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
 
   CGFloat ct_font_size = CTFontGetSize (ct_font);
   CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
   CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
 
   /* Attach marks to their bases, to match the 'ot' shaper.
-   * Adapted from hb-ot-shape:hb_form_clusters().
+   * Adapted from a very old version of hb-ot-shape:hb_form_clusters().
    * Note that this only makes us be closer to the 'ot' shaper,
    * but by no means the same.  For example, if there's
    * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
@@ -641,8 +476,8 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
        buffer->merge_clusters (i - 1, i + 1);
   }
 
-  hb_auto_t<hb_vector_t<feature_record_t> > feature_records;
-  hb_auto_t<hb_vector_t<range_record_t> > range_records;
+  hb_vector_t<feature_record_t> feature_records;
+  hb_vector_t<range_record_t> range_records;
 
   /*
    * Set up features.
@@ -651,14 +486,10 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
   if (num_features)
   {
     /* Sort features by start/end events. */
-    hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
+    hb_vector_t<feature_event_t> feature_events;
     for (unsigned int i = 0; i < num_features; i++)
     {
-      const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
-                                                                              feature_mappings,
-                                                                              ARRAY_LENGTH (feature_mappings),
-                                                                              sizeof (feature_mappings[0]),
-                                                                              _hb_feature_mapping_cmp);
+      const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
       if (!mapping)
         continue;
 
@@ -694,9 +525,9 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
     }
 
     /* Scan events and save features for each range. */
-    hb_auto_t<hb_vector_t<active_feature_t> > active_features;
+    hb_vector_t<active_feature_t> active_features;
     unsigned int last_index = 0;
-    for (unsigned int i = 0; i < feature_events.len; i++)
+    for (unsigned int i = 0; i < feature_events.length; i++)
     {
       feature_event_t *event = &feature_events[i];
 
@@ -705,13 +536,13 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
         /* Save a snapshot of active features and the range. */
        range_record_t *range = range_records.push ();
 
-       if (active_features.len)
+       if (active_features.length)
        {
          CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
 
          /* TODO sort and resolve conflicting features? */
          /* active_features.qsort (); */
-         for (unsigned int j = 0; j < active_features.len; j++)
+         for (unsigned int j = 0; j < active_features.length; j++)
          {
            CFStringRef keys[] = {
              kCTFontFeatureTypeIdentifierKey,
@@ -767,7 +598,7 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
       } else {
         active_feature_t *feature = active_features.find (&event->feature);
        if (feature)
-         active_features.remove (feature - active_features.arrayZ);
+         active_features.remove (feature - active_features.arrayZ ());
       }
     }
   }
@@ -824,7 +655,7 @@ _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
   CFStringRef string_ref = nullptr;
   CTLineRef line = nullptr;
 
-  if (0)
+  if (false)
   {
 resize_and_retry:
     DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
@@ -899,7 +730,7 @@ resize_and_retry:
       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
                                      kCTFontAttributeName, ct_font);
 
-      if (num_features && range_records.len)
+      if (num_features && range_records.length)
       {
        unsigned int start = 0;
        range_record_t *last_range = &range_records[0];
@@ -1048,7 +879,7 @@ resize_and_retry:
         * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
         */
        bool matched = false;
-       for (unsigned int i = 0; i < range_records.len; i++)
+       for (unsigned int i = 0; i < range_records.length; i++)
          if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
          {
            matched = true;
@@ -1235,7 +1066,7 @@ resize_and_retry:
      *
      * https://crbug.com/419769
      */
-    if (0)
+    if (false)
     {
       /* Make sure all runs had the expected direction. */
       bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
@@ -1311,7 +1142,7 @@ fail:
   if (line)
     CFRelease (line);
 
-  for (unsigned int i = 0; i < range_records.len; i++)
+  for (unsigned int i = 0; i < range_records.length; i++)
     if (range_records[i].font)
       CFRelease (range_records[i].font);
 
@@ -1323,36 +1154,21 @@ fail:
  * AAT shaper
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
-
 /*
  * shaper face data
  */
 
-struct hb_coretext_aat_shaper_face_data_t {};
+struct hb_coretext_aat_face_data_t {};
 
-hb_coretext_aat_shaper_face_data_t *
+hb_coretext_aat_face_data_t *
 _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
 {
-  static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
-  {
-    hb_blob_t *blob = face->reference_table (tags[i]);
-    if (hb_blob_get_length (blob))
-    {
-      hb_blob_destroy (blob);
-      return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-    }
-    hb_blob_destroy (blob);
-  }
-
-  return nullptr;
+  return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
+        (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -1361,38 +1177,16 @@ _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *d
  * shaper font data
  */
 
-struct hb_coretext_aat_shaper_font_data_t {};
+struct hb_coretext_aat_font_data_t {};
 
-hb_coretext_aat_shaper_font_data_t *
+hb_coretext_aat_font_data_t *
 _hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
 {
-  return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-}
-
-void
-_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_aat_shaper_shape_plan_data_t {};
-
-hb_coretext_aat_shaper_shape_plan_data_t *
-_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
 {
 }
 
index c244347..d7d0165 100644 (file)
 #ifndef HB_DEBUG_HH
 #define HB_DEBUG_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-dsalgs.hh"
 
 
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
 
+
+/*
+ * Global runtime options.
+ */
+
+struct hb_options_t
+{
+  bool unused : 1; /* In-case sign bit is here. */
+  bool initialized : 1;
+  bool uniscribe_bug_compatible : 1;
+  bool aat : 1;
+};
+
+union hb_options_union_t {
+  int i;
+  hb_options_t opts;
+};
+static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+
+HB_INTERNAL void
+_hb_options_init ();
+
+extern HB_INTERNAL hb_atomic_int_t _hb_options;
+
+static inline hb_options_t
+hb_options ()
+{
+  /* Make a local copy, so we can access bitfield threadsafely. */
+  hb_options_union_t u;
+  u.i = _hb_options.get_relaxed ();
+
+  if (unlikely (!u.i))
+  {
+    _hb_options_init ();
+    u.i = _hb_options.get_relaxed ();
+  }
+
+  return u.opts;
+}
+
+
+/*
+ * Debug output (needs enabling at compile time.)
+ */
+
 static inline bool
 _hb_debug (unsigned int level,
           unsigned int max_level)
@@ -126,7 +173,7 @@ _hb_debug_msg_va (const char *what,
 
   fprintf (stderr, "\n");
 }
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 0)
 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
                     const void *obj HB_UNUSED,
                     const char *func HB_UNUSED,
@@ -145,7 +192,7 @@ _hb_debug_msg (const char *what,
               int level_dir,
               const char *message,
               ...) HB_PRINTF_FUNC(7, 8);
-template <int max_level> static inline void
+template <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg (const char *what,
               const void *obj,
               const char *func,
@@ -169,7 +216,7 @@ _hb_debug_msg<0> (const char *what HB_UNUSED,
                  int level_dir HB_UNUSED,
                  const char *message HB_UNUSED,
                  ...) HB_PRINTF_FUNC(7, 8);
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg<0> (const char *what HB_UNUSED,
                  const void *obj HB_UNUSED,
                  const char *func HB_UNUSED,
@@ -237,7 +284,7 @@ struct hb_auto_trace_t
     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
     va_end (ap);
   }
-  inline ~hb_auto_trace_t (void)
+  ~hb_auto_trace_t ()
   {
     _hb_warn_no_return<ret_t> (returned);
     if (!returned) {
@@ -246,14 +293,16 @@ struct hb_auto_trace_t
     if (plevel) --*plevel;
   }
 
-  inline ret_t ret (ret_t v, unsigned int line = 0)
+  ret_t ret (ret_t v,
+            const char *func = "",
+            unsigned int line = 0)
   {
     if (unlikely (returned)) {
       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
       return v;
     }
 
-    _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
+    _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
                              "return %s (line %d)",
                              hb_printer_t<ret_t>().print (v), line);
     if (plevel) --*plevel;
@@ -278,17 +327,21 @@ struct hb_auto_trace_t<0, ret_t>
                                   const char *message,
                                   ...) HB_PRINTF_FUNC(6, 7) {}
 
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+            const char *func HB_UNUSED = nullptr,
+            unsigned int line HB_UNUSED = 0) { return v; }
 };
 
 /* For disabled tracing; optimize out everything.
  * https://github.com/harfbuzz/harfbuzz/pull/605 */
 template <typename ret_t>
 struct hb_no_trace_t {
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+            const char *func HB_UNUSED = "",
+            unsigned int line HB_UNUSED = 0) { return v; }
 };
 
-#define return_trace(RET) return trace.ret (RET, __LINE__)
+#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
 
 
 /*
@@ -348,30 +401,6 @@ struct hb_no_trace_t {
 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
 #endif
 
-#ifndef HB_DEBUG_CLOSURE
-#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_CLOSURE
-#define TRACE_CLOSURE(this) \
-       hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
-       (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-        " ")
-#else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
-#ifndef HB_DEBUG_COLLECT_GLYPHS
-#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_COLLECT_GLYPHS
-#define TRACE_COLLECT_GLYPHS(this) \
-       hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
-       (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-        " ")
-#else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
 #ifndef HB_DEBUG_SANITIZE
 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 #endif
@@ -423,8 +452,6 @@ struct hb_no_trace_t {
 #ifndef HB_DEBUG_DISPATCH
 #define HB_DEBUG_DISPATCH ( \
        HB_DEBUG_APPLY + \
-       HB_DEBUG_CLOSURE + \
-       HB_DEBUG_COLLECT_GLYPHS + \
        HB_DEBUG_SANITIZE + \
        HB_DEBUG_SERIALIZE + \
   HB_DEBUG_SUBSET + \
index eac7efb..4a5e702 100644 (file)
 #include "hb-font.h"
 #include "hb-set.h"
 
+
+/**
+ * SECTION:hb-deprecated
+ * @title: hb-deprecated
+ * @short_description: Deprecated API
+ * @include: hb.h
+ *
+ * These API have been deprecated in favor of newer API, or because they
+ * were deemed unnecessary.
+ **/
+
+
 HB_BEGIN_DECLS
 
 #ifndef HB_DISABLE_DEPRECATED
 
+
 #define HB_SCRIPT_CANADIAN_ABORIGINAL          HB_SCRIPT_CANADIAN_SYLLABICS
 
 #define HB_BUFFER_FLAGS_DEFAULT                        HB_BUFFER_FLAG_DEFAULT
@@ -50,14 +63,162 @@ typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
                                               hb_codepoint_t *glyph,
                                               void *user_data);
 
-HB_EXTERN void
+HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
                              hb_font_get_glyph_func_t func,
                              void *user_data, hb_destroy_func_t destroy);
 
-HB_EXTERN void
+HB_EXTERN HB_DEPRECATED void
 hb_set_invert (hb_set_t *set);
 
+/**
+ * hb_unicode_eastasian_width_func_t:
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                   (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                hb_codepoint_t      unicode,
+                                                                                void               *user_data);
+
+/**
+ * hb_unicode_funcs_set_eastasian_width_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
+                                          hb_unicode_eastasian_width_func_t func,
+                                          void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_unicode_eastasian_width:
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
+                           hb_codepoint_t unicode);
+
+
+/**
+ * hb_unicode_decompose_compatibility_func_t:
+ * @ufuncs: a Unicode function structure
+ * @u: codepoint to decompose
+ * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
+ * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
+ *
+ * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
+ * The complete length of the decomposition will be returned.
+ *
+ * If @u has no compatibility decomposition, zero should be returned.
+ *
+ * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
+ * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
+ * of this function type must ensure that they do not write past the provided array.
+ *
+ * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                   (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                        hb_codepoint_t      u,
+                                                                                        hb_codepoint_t     *decomposed,
+                                                                                        void               *user_data);
+
+/**
+ * HB_UNICODE_MAX_DECOMPOSITION_LEN:
+ *
+ * See Unicode 6.1 for details on the maximum decomposition length.
+ *
+ * Deprecated: 2.0.0
+ */
+#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
+
+/**
+ * hb_unicode_funcs_set_decompose_compatibility_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
+                                                  hb_unicode_decompose_compatibility_func_t func,
+                                                  void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
+                                   hb_codepoint_t      u,
+                                   hb_codepoint_t     *decomposed);
+
+
+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
+                                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                                          void *user_data);
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+
+/**
+ * hb_font_funcs_set_glyph_h_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_glyph_h_kerning_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * 
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_glyph_v_kerning_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+                            hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+HB_EXTERN hb_position_t
+hb_font_get_glyph_v_kerning (hb_font_t *font,
+                            hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
+
+HB_EXTERN void
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+                                        hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                        hb_direction_t direction,
+                                        hb_position_t *x, hb_position_t *y);
+
+
 #endif
 
 HB_END_DECLS
index 187ab3f..aaf10a1 100644 (file)
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#define HB_SHAPER directwrite
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
 
 #include <DWrite_1.h>
 
 #include "hb-directwrite.h"
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE (directwrite, face)
-HB_SHAPER_DATA_ENSURE_DEFINE (directwrite, font)
-
-
 /*
  * hb-directwrite uses new/delete syntatically but as we let users
  * to override malloc/free, we will redefine new/delete so users
  * won't need to do that by their own.
  */
-void* operator new (size_t size) { return malloc (size); }
-void* operator new [] (size_t size) { return malloc (size); }
-void operator delete (void* pointer) { free (pointer); }
+void* operator new (size_t size)        { return malloc (size); }
+void* operator new [] (size_t size)     { return malloc (size); }
+void operator delete (void* pointer)    { free (pointer); }
 void operator delete [] (void* pointer) { free (pointer); }
 
 
@@ -60,23 +54,25 @@ private:
   IDWriteFontFileStream *mFontFileStream;
 public:
   DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream)
-  {
-    mFontFileStream = fontFileStream;
-  }
+  { mFontFileStream = fontFileStream; }
 
   // IUnknown interface
-  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) { return S_OK; }
-  IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
+  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+  { return S_OK; }
+  IFACEMETHOD_ (ULONG, AddRef) ()  { return 1; }
   IFACEMETHOD_ (ULONG, Release) () { return 1; }
 
   // IDWriteFontFileLoader methods
-  virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey (void const* fontFileReferenceKey,
-    uint32_t fontFileReferenceKeySize,
-    OUT IDWriteFontFileStream** fontFileStream)
+  virtual HRESULT STDMETHODCALLTYPE
+  CreateStreamFromKey (void const* fontFileReferenceKey,
+                      uint32_t fontFileReferenceKeySize,
+                      OUT IDWriteFontFileStream** fontFileStream)
   {
     *fontFileStream = mFontFileStream;
     return S_OK;
   }
+
+  virtual ~DWriteFontFileLoader() {}
 };
 
 class DWriteFontFileStream : public IDWriteFontFileStream
@@ -92,19 +88,20 @@ public:
   }
 
   // IUnknown interface
-  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) { return S_OK; }
-  IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
+  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+  { return S_OK; }
+  IFACEMETHOD_ (ULONG, AddRef) ()  { return 1; }
   IFACEMETHOD_ (ULONG, Release) () { return 1; }
 
   // IDWriteFontFileStream methods
-  virtual HRESULT STDMETHODCALLTYPE ReadFileFragment (void const** fragmentStart,
-    UINT64 fileOffset,
-    UINT64 fragmentSize,
-    OUT void** fragmentContext)
+  virtual HRESULT STDMETHODCALLTYPE
+  ReadFileFragment (void const** fragmentStart,
+                   UINT64 fileOffset,
+                   UINT64 fragmentSize,
+                   OUT void** fragmentContext)
   {
     // We are required to do bounds checking.
-    if (fileOffset + fragmentSize > mSize)
-      return E_FAIL;
+    if (fileOffset + fragmentSize > mSize) return E_FAIL;
 
     // truncate the 64 bit fileOffset to size_t sized index into mData
     size_t index = static_cast<size_t> (fileOffset);
@@ -115,18 +112,20 @@ public:
     return S_OK;
   }
 
-  virtual void STDMETHODCALLTYPE ReleaseFileFragment (void* fragmentContext) { }
+  virtual void STDMETHODCALLTYPE
+  ReleaseFileFragment (void* fragmentContext) {}
 
-  virtual HRESULT STDMETHODCALLTYPE GetFileSize (OUT UINT64* fileSize)
+  virtual HRESULT STDMETHODCALLTYPE
+  GetFileSize (OUT UINT64* fileSize)
   {
     *fileSize = mSize;
     return S_OK;
   }
 
-  virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime (OUT UINT64* lastWriteTime)
-  {
-    return E_NOTIMPL;
-  }
+  virtual HRESULT STDMETHODCALLTYPE
+  GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; }
+
+  virtual ~DWriteFontFileStream() {}
 };
 
 
@@ -134,36 +133,33 @@ public:
 * shaper face data
 */
 
-struct hb_directwrite_shaper_face_data_t
+struct hb_directwrite_face_data_t
 {
   IDWriteFactory *dwriteFactory;
   IDWriteFontFile *fontFile;
-  IDWriteFontFileStream *fontFileStream;
-  IDWriteFontFileLoader *fontFileLoader;
+  DWriteFontFileStream *fontFileStream;
+  DWriteFontFileLoader *fontFileLoader;
   IDWriteFontFace *fontFace;
   hb_blob_t *faceBlob;
 };
 
-hb_directwrite_shaper_face_data_t *
+hb_directwrite_face_data_t *
 _hb_directwrite_shaper_face_data_create (hb_face_t *face)
 {
-  hb_directwrite_shaper_face_data_t *data = new hb_directwrite_shaper_face_data_t;
+  hb_directwrite_face_data_t *data = new hb_directwrite_face_data_t;
   if (unlikely (!data))
     return nullptr;
 
   // TODO: factory and fontFileLoader should be cached separately
   IDWriteFactory* dwriteFactory;
-  DWriteCreateFactory (
-    DWRITE_FACTORY_TYPE_SHARED,
-    __uuidof (IDWriteFactory),
-    (IUnknown**) &dwriteFactory
-  );
+  DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+                      (IUnknown**) &dwriteFactory);
 
   HRESULT hr;
   hb_blob_t *blob = hb_face_reference_blob (face);
-  DWriteFontFileStream *fontFileStream = new DWriteFontFileStream (
-    (uint8_t *) hb_blob_get_data (blob, nullptr),
-    hb_blob_get_length (blob));
+  DWriteFontFileStream *fontFileStream;
+  fontFileStream = new DWriteFontFileStream ((uint8_t *) hb_blob_get_data (blob, nullptr),
+                                            hb_blob_get_length (blob));
 
   DWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream);
   dwriteFactory->RegisterFontFileLoader (fontFileLoader);
@@ -171,7 +167,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
   IDWriteFontFile *fontFile;
   uint64_t fontFileKey = 0;
   hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
-      fontFileLoader, &fontFile);
+                                                    fontFileLoader, &fontFile);
 
 #define FAIL(...) \
   HB_STMT_START { \
@@ -194,7 +190,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
 
   IDWriteFontFace *fontFace;
   dwriteFactory->CreateFontFace (faceType, 1, &fontFile, 0,
-    DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
+                                DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
 
   data->dwriteFactory = dwriteFactory;
   data->fontFile = fontFile;
@@ -207,7 +203,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
 }
 
 void
-_hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *data)
+_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
 {
   if (data->fontFace)
     data->fontFace->Release ();
@@ -234,16 +230,12 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *dat
  * shaper font data
  */
 
-struct hb_directwrite_shaper_font_data_t
-{
-};
+struct hb_directwrite_font_data_t {};
 
-hb_directwrite_shaper_font_data_t *
+hb_directwrite_font_data_t *
 _hb_directwrite_shaper_font_data_create (hb_font_t *font)
 {
-  if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return nullptr;
-
-  hb_directwrite_shaper_font_data_t *data = new hb_directwrite_shaper_font_data_t;
+  hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
   if (unlikely (!data))
     return nullptr;
 
@@ -251,41 +243,20 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
 }
 
 void
-_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data)
+_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
 {
   delete data;
 }
 
 
-/*
- * shaper shape_plan data
- */
-
-struct hb_directwrite_shaper_shape_plan_data_t {};
-
-hb_directwrite_shaper_shape_plan_data_t *
-_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                              const hb_feature_t *user_features HB_UNUSED,
-                                              unsigned int        num_user_features HB_UNUSED,
-                                              const int          *coords HB_UNUSED,
-                                              unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
 // Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
 // but now is relicensed to MIT for HarfBuzz use
-class TextAnalysis
-  : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
+class TextAnalysis : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
 {
 public:
 
-  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) { return S_OK; }
+  IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
+  { return S_OK; }
   IFACEMETHOD_ (ULONG, AddRef) () { return 1; }
   IFACEMETHOD_ (ULONG, Release) () { return 1; }
 
@@ -302,7 +273,7 @@ public:
     uint8_t mBidiLevel;
     bool mIsSideways;
 
-    inline bool ContainsTextPosition (uint32_t aTextPosition) const
+    bool ContainsTextPosition (uint32_t aTextPosition) const
     {
       return aTextPosition >= mTextStart &&
             aTextPosition <  mTextStart + mTextLength;
@@ -312,16 +283,10 @@ public:
   };
 
 public:
-  TextAnalysis (const wchar_t* text,
-    uint32_t textLength,
-    const wchar_t* localeName,
-    DWRITE_READING_DIRECTION readingDirection)
-    : mText (text)
-    , mTextLength (textLength)
-    , mLocaleName (localeName)
-    , mReadingDirection (readingDirection)
-    , mCurrentRun (nullptr) { };
-
+  TextAnalysis (const wchar_t* text, uint32_t textLength,
+               const wchar_t* localeName, DWRITE_READING_DIRECTION readingDirection)
+              : mTextLength (textLength), mText (text), mLocaleName (localeName),
+                mReadingDirection (readingDirection), mCurrentRun (nullptr) {}
   ~TextAnalysis ()
   {
     // delete runs, except mRunHead which is part of the TextAnalysis object
@@ -333,8 +298,8 @@ public:
     }
   }
 
-  STDMETHODIMP GenerateResults (IDWriteTextAnalyzer* textAnalyzer,
-    Run **runHead)
+  STDMETHODIMP
+  GenerateResults (IDWriteTextAnalyzer* textAnalyzer, Run **runHead)
   {
     // Analyzes the text using the script analyzer and returns
     // the result as a series of runs.
@@ -359,9 +324,10 @@ public:
 
   // IDWriteTextAnalysisSource implementation
 
-  IFACEMETHODIMP GetTextAtPosition (uint32_t textPosition,
-    OUT wchar_t const** textString,
-    OUT uint32_t* textLength)
+  IFACEMETHODIMP
+  GetTextAtPosition (uint32_t textPosition,
+                    OUT wchar_t const** textString,
+                    OUT uint32_t* textLength)
   {
     if (textPosition >= mTextLength)
     {
@@ -377,9 +343,10 @@ public:
     return S_OK;
   }
 
-  IFACEMETHODIMP GetTextBeforePosition (uint32_t textPosition,
-    OUT wchar_t const** textString,
-    OUT uint32_t* textLength)
+  IFACEMETHODIMP
+  GetTextBeforePosition (uint32_t textPosition,
+                        OUT wchar_t const** textString,
+                        OUT uint32_t* textLength)
   {
     if (textPosition == 0 || textPosition > mTextLength)
     {
@@ -397,19 +364,16 @@ public:
   }
 
   IFACEMETHODIMP_ (DWRITE_READING_DIRECTION)
-    GetParagraphReadingDirection () { return mReadingDirection; }
+  GetParagraphReadingDirection () { return mReadingDirection; }
 
-  IFACEMETHODIMP GetLocaleName (uint32_t textPosition,
-    uint32_t* textLength,
-    wchar_t const** localeName)
-  {
-    return S_OK;
-  }
+  IFACEMETHODIMP GetLocaleName (uint32_t textPosition, uint32_t* textLength,
+                               wchar_t const** localeName)
+  { return S_OK; }
 
   IFACEMETHODIMP
-    GetNumberSubstitution (uint32_t textPosition,
-    OUT uint32_t* textLength,
-    OUT IDWriteNumberSubstitution** numberSubstitution)
+  GetNumberSubstitution (uint32_t textPosition,
+                        OUT uint32_t* textLength,
+                        OUT IDWriteNumberSubstitution** numberSubstitution)
   {
     // We do not support number substitution.
     *numberSubstitution = nullptr;
@@ -421,9 +385,8 @@ public:
   // IDWriteTextAnalysisSink implementation
 
   IFACEMETHODIMP
-    SetScriptAnalysis (uint32_t textPosition,
-    uint32_t textLength,
-    DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
+  SetScriptAnalysis (uint32_t textPosition, uint32_t textLength,
+                    DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
   {
     SetCurrentRun (textPosition);
     SplitCurrentRun (textPosition);
@@ -437,19 +400,19 @@ public:
   }
 
   IFACEMETHODIMP
-    SetLineBreakpoints (uint32_t textPosition,
-    uint32_t textLength,
-    const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; }
+  SetLineBreakpoints (uint32_t textPosition,
+                     uint32_t textLength,
+                     const DWRITE_LINE_BREAKPOINT* lineBreakpoints)
+  { return S_OK; }
 
-  IFACEMETHODIMP SetBidiLevel (uint32_t textPosition,
-    uint32_t textLength,
-    uint8_t explicitLevel,
-    uint8_t resolvedLevel) { return S_OK; }
+  IFACEMETHODIMP SetBidiLevel (uint32_t textPosition, uint32_t textLength,
+                              uint8_t explicitLevel, uint8_t resolvedLevel)
+  { return S_OK; }
 
   IFACEMETHODIMP
-    SetNumberSubstitution (uint32_t textPosition,
-    uint32_t textLength,
-    IDWriteNumberSubstitution* numberSubstitution) { return S_OK; }
+  SetNumberSubstitution (uint32_t textPosition, uint32_t textLength,
+                        IDWriteNumberSubstitution* numberSubstitution)
+  { return S_OK; }
 
 protected:
   Run *FetchNextRun (IN OUT uint32_t* textLength)
@@ -549,15 +512,14 @@ static inline uint32_t hb_uint32_swap (const uint32_t v)
 
 static hb_bool_t
 _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
-  hb_font_t          *font,
-  hb_buffer_t        *buffer,
-  const hb_feature_t *features,
-  unsigned int        num_features,
-  float               lineWidth)
+                           hb_font_t          *font,
+                           hb_buffer_t        *buffer,
+                           const hb_feature_t *features,
+                           unsigned int        num_features,
+                           float               lineWidth)
 {
   hb_face_t *face = font->face;
-  hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+  const hb_directwrite_face_data_t *face_data = face->data.directwrite;
   IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
   IDWriteFontFace *fontFace = face_data->fontFace;
 
@@ -609,9 +571,10 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
 
   // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
 
-  DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ?
-    DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
-    DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+  DWRITE_READING_DIRECTION readingDirection;
+  readingDirection = buffer->props.direction ?
+                    DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
+                    DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
 
   /*
   * There's an internal 16-bit limit on some things inside the analyzer,
@@ -640,10 +603,8 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
 
   const wchar_t localeName[20] = {0};
   if (buffer->props.language != nullptr)
-  {
     mbstowcs ((wchar_t*) localeName,
-      hb_language_to_string (buffer->props.language), 20);
-  }
+             hb_language_to_string (buffer->props.language), 20);
 
   // TODO: it does work but doesn't care about ranges
   DWRITE_TYPOGRAPHIC_FEATURES typographic_features;
@@ -654,27 +615,29 @@ _hb_directwrite_shape_full (hb_shape_plan_t    *shape_plan,
     for (unsigned int i = 0; i < num_features; ++i)
     {
       typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
-       hb_uint32_swap (features[i].tag);
+                                                hb_uint32_swap (features[i].tag);
       typographic_features.features[i].parameter = features[i].value;
     }
   }
-  const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures =
-    (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features;
+  const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures;
+  dwFeatures = (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features;
   const uint32_t featureRangeLengths[] = { textLength };
   //
 
-  uint16_t* clusterMap = new uint16_t[textLength];
-  DWRITE_SHAPING_TEXT_PROPERTIES* textProperties =
-    new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
+  uint16_t* clusterMap;
+  clusterMap = new uint16_t[textLength];
+  DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
+  textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
 retry_getglyphs:
   uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
-  DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties =
-    new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
+  DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
+  glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
 
   hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
-    isRightToLeft, &runHead->mScript, localeName, nullptr, &dwFeatures,
-    featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
-    glyphProperties, &glyphCount);
+                           isRightToLeft, &runHead->mScript, localeName,
+                           nullptr, &dwFeatures, featureRangeLengths, 1,
+                           maxGlyphCount, clusterMap, textProperties,
+                           glyphIndices, glyphProperties, &glyphCount);
 
   if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
   {
@@ -694,30 +657,28 @@ retry_getglyphs:
   /* The -2 in the following is to compensate for possible
    * alignment needed after the WORD array.  sizeof (WORD) == 2. */
   unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
-         / (sizeof (WORD) +
-            sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
-            sizeof (int) +
-            sizeof (DWRITE_GLYPH_OFFSET) +
-            sizeof (uint32_t));
+                            / (sizeof (WORD) +
+                               sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
+                               sizeof (int) +
+                               sizeof (DWRITE_GLYPH_OFFSET) +
+                               sizeof (uint32_t));
   ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
 
 #undef ALLOCATE_ARRAY
 
   int fontEmSize = font->face->get_upem ();
-  if (fontEmSize < 0)
-    fontEmSize = -fontEmSize;
+  if (fontEmSize < 0) fontEmSize = -fontEmSize;
 
-  if (fontEmSize < 0)
-    fontEmSize = -fontEmSize;
+  if (fontEmSize < 0) fontEmSize = -fontEmSize;
   double x_mult = (double) font->x_scale / fontEmSize;
   double y_mult = (double) font->y_scale / fontEmSize;
 
-  hr = analyzer->GetGlyphPlacements (textString,
-    clusterMap, textProperties, textLength, glyphIndices,
-    glyphProperties, glyphCount, fontFace, fontEmSize,
-    false, isRightToLeft, &runHead->mScript, localeName,
-    &dwFeatures, featureRangeLengths, 1,
-    glyphAdvances, glyphOffsets);
+  hr = analyzer->GetGlyphPlacements (textString, clusterMap, textProperties,
+                                    textLength, glyphIndices, glyphProperties,
+                                    glyphCount, fontFace, fontEmSize,
+                                    false, isRightToLeft, &runHead->mScript, localeName,
+                                    &dwFeatures, featureRangeLengths, 1,
+                                    glyphAdvances, glyphOffsets);
 
   if (FAILED (hr))
     FAIL ("Analyzer failed to get glyph placements.");
@@ -727,12 +688,12 @@ retry_getglyphs:
 
   if (analyzer1 && lineWidth)
   {
-
     DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
       new DWRITE_JUSTIFICATION_OPPORTUNITY[maxGlyphCount];
-    hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize,
-      runHead->mScript, textLength, glyphCount, textString, clusterMap,
-      glyphProperties, justificationOpportunities);
+    hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize, runHead->mScript,
+                                                  textLength, glyphCount, textString,
+                                                  clusterMap, glyphProperties,
+                                                  justificationOpportunities);
 
     if (FAILED (hr))
       FAIL ("Analyzer failed to get justification opportunities.");
@@ -740,15 +701,14 @@ retry_getglyphs:
     float* justifiedGlyphAdvances = new float[maxGlyphCount];
     DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount];
     hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
-      glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
+                                         glyphAdvances, glyphOffsets, justifiedGlyphAdvances,
+                                         justifiedGlyphOffsets);
 
-    if (FAILED (hr))
-      FAIL ("Analyzer failed to get justified glyph advances.");
+    if (FAILED (hr)) FAIL ("Analyzer failed to get justify glyph advances.");
 
     DWRITE_SCRIPT_PROPERTIES scriptProperties;
     hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties);
-    if (FAILED (hr))
-      FAIL ("Analyzer failed to get script properties.");
+    if (FAILED (hr)) FAIL ("Analyzer failed to get script properties.");
     uint32_t justificationCharacter = scriptProperties.justificationCharacter;
 
     // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
@@ -758,14 +718,15 @@ retry_getglyphs:
     retry_getjustifiedglyphs:
       uint16_t* modifiedGlyphIndices = new uint16_t[maxGlyphCount];
       float* modifiedGlyphAdvances = new float[maxGlyphCount];
-      DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets =
-       new DWRITE_GLYPH_OFFSET[maxGlyphCount];
+      DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
       uint32_t actualGlyphsCount;
       hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
-       textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices,
-       glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
-       glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
-       modifiedGlyphAdvances, modifiedGlyphOffsets);
+                                         textLength, glyphCount, maxGlyphCount,
+                                         clusterMap, glyphIndices, glyphAdvances,
+                                         justifiedGlyphAdvances, justifiedGlyphOffsets,
+                                         glyphProperties, &actualGlyphsCount,
+                                         modifiedClusterMap, modifiedGlyphIndices,
+                                         modifiedGlyphAdvances, modifiedGlyphOffsets);
 
       if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
       {
@@ -805,7 +766,6 @@ retry_getglyphs:
     }
 
     delete [] justificationOpportunities;
-
   }
 
   /* Ok, we've got everything we need, now compose output buffer,
@@ -813,7 +773,7 @@ retry_getglyphs:
 
   /* Calculate visual-clusters.  That's what we ship. */
   for (unsigned int i = 0; i < glyphCount; i++)
-    vis_clusters[i] = -1;
+    vis_clusters[i] = (uint32_t) -1;
   for (unsigned int i = 0; i < buffer->len; i++)
   {
     uint32_t *p =
@@ -821,7 +781,7 @@ retry_getglyphs:
     *p = MIN (*p, buffer->info[i].cluster);
   }
   for (unsigned int i = 1; i < glyphCount; i++)
-    if (vis_clusters[i] == -1)
+    if (vis_clusters[i] == (uint32_t) -1)
       vis_clusters[i] = vis_clusters[i - 1];
 
 #undef utf16_index
@@ -855,13 +815,11 @@ retry_getglyphs:
 
     /* TODO vertical */
     pos->x_advance = x_mult * (int32_t) info->mask;
-    pos->x_offset =
-      x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
+    pos->x_offset = x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
     pos->y_offset = y_mult * info->var2.i32;
   }
 
-  if (isRightToLeft)
-    hb_buffer_reverse (buffer);
+  if (isRightToLeft) hb_buffer_reverse (buffer);
 
   delete [] clusterMap;
   delete [] glyphIndices;
@@ -879,13 +837,13 @@ retry_getglyphs:
 
 hb_bool_t
 _hb_directwrite_shape (hb_shape_plan_t    *shape_plan,
-  hb_font_t          *font,
-  hb_buffer_t        *buffer,
-  const hb_feature_t *features,
-  unsigned int        num_features)
+                      hb_font_t          *font,
+                      hb_buffer_t        *buffer,
+                      const hb_feature_t *features,
+                      unsigned int        num_features)
 {
   return _hb_directwrite_shape_full (shape_plan, font, buffer,
-    features, num_features, 0);
+                                    features, num_features, 0);
 }
 
 /*
@@ -894,16 +852,17 @@ _hb_directwrite_shape (hb_shape_plan_t    *shape_plan,
 
 hb_bool_t
 hb_directwrite_shape_experimental_width (hb_font_t          *font,
-  hb_buffer_t        *buffer,
-  const hb_feature_t *features,
-  unsigned int        num_features,
-  float               width)
+                                        hb_buffer_t        *buffer,
+                                        const hb_feature_t *features,
+                                        unsigned int        num_features,
+                                        float               width)
 {
   static const char *shapers = "directwrite";
-  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face,
-    &buffer->props, features, num_features, &shapers);
+  hb_shape_plan_t *shape_plan;
+  shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
+                                           features, num_features, &shapers);
   hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
-    features, num_features, width);
+                                             features, num_features, width);
 
   buffer->unsafe_to_break_all ();
 
index 9586871..cb3057c 100644 (file)
 #ifndef HB_DSALGS_HH
 #define HB_DSALGS_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-null.hh"
 
 
+/* Void! For when we need a expression-type of void. */
+typedef const struct _hb_void_t *hb_void_t;
+#define HB_VOID ((const _hb_void_t *) nullptr)
+
+
+/*
+ * Bithacks.
+ */
+
+/* Return the number of 1 bits in v. */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_popcount (T v)
+{
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_popcount (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_popcountl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_popcountll (v);
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "HACKMEM 169" */
+    uint32_t y;
+    y = (v >> 1) &033333333333;
+    y = v - y - ((y >>1) & 033333333333);
+    return (((y + (y >> 3)) & 030707070707) % 077);
+  }
+
+  if (sizeof (T) == 8)
+  {
+    unsigned int shift = 32;
+    return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
+  }
+
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of bits needed to store number */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_bit_storage (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return sizeof (unsigned int) * 8 - __builtin_clz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanReverse (&where, v);
+    return 1 + where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanReverse64 (&where, v);
+    return 1 + where;
+  }
+# endif
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+    const unsigned int S[] = {1, 2, 4, 8, 16};
+    unsigned int r = 0;
+    for (int i = 4; i >= 0; i--)
+      if (v & b[i])
+      {
+       v >>= S[i];
+       r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
+    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
+    unsigned int r = 0;
+    for (int i = 5; i >= 0; i--)
+      if (v & b[i])
+      {
+       v >>= S[i];
+       r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
+                         hb_bit_storage<uint64_t> ((uint64_t) v);
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of zero bits in the least significant side of v */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_ctz (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_ctz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_ctzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_ctzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanForward (&where, v);
+    return where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanForward64 (&where, v);
+    return where;
+  }
+# endif
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    unsigned int c = 32;
+    v &= - (int32_t) v;
+    if (v) c--;
+    if (v & 0x0000FFFF) c -= 16;
+    if (v & 0x00FF00FF) c -= 8;
+    if (v & 0x0F0F0F0F) c -= 4;
+    if (v & 0x33333333) c -= 2;
+    if (v & 0x55555555) c -= 1;
+    return c;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    unsigned int c = 64;
+    v &= - (int64_t) (v);
+    if (v) c--;
+    if (v & 0x00000000FFFFFFFFULL) c -= 32;
+    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
+    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
+    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
+    if (v & 0x3333333333333333ULL) c -= 2;
+    if (v & 0x5555555555555555ULL) c -= 1;
+    return c;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
+                         hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+
+/*
+ * Tiny stuff.
+ */
+
+template <typename T>
+static inline T* hb_addressof (T& arg)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  /* https://en.cppreference.com/w/cpp/memory/addressof */
+  return reinterpret_cast<T*>(
+          &const_cast<char&>(
+             reinterpret_cast<const volatile char&>(arg)));
+#pragma GCC diagnostic pop
+}
+
+/* ASCII tag/character handling */
+static inline bool ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline bool ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline bool ISSPACE (unsigned char c)
+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
+#undef MIN
+template <typename Type>
+static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
+
+#undef MAX
+template <typename Type>
+static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
+
+static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
+{ return (a + (b - 1)) / b; }
+
+
+#undef  ARRAY_LENGTH
+template <typename Type, unsigned int n>
+static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
+/* A const version, but does not detect erratically being called on pointers. */
+#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
+
+
+static inline int
+hb_memcmp (const void *a, const void *b, unsigned int len)
+{
+  /* It's illegal to pass NULL to memcmp(), even if len is zero.
+   * So, wrap it.
+   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
+  if (!len) return 0;
+  return memcmp (a, b, len);
+}
+
+static inline bool
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+{
+  return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+static inline unsigned int
+hb_ceil_to_4 (unsigned int v)
+{
+  return ((v - 1) | 3) + 1;
+}
+
+template <typename T> struct hb_is_signed;
+template <> struct hb_is_signed<signed char> { enum { value = true }; };
+template <> struct hb_is_signed<signed short> { enum { value = true }; };
+template <> struct hb_is_signed<signed int> { enum { value = true }; };
+template <> struct hb_is_signed<signed long> { enum { value = true }; };
+template <> struct hb_is_signed<unsigned char> { enum { value = false }; };
+template <> struct hb_is_signed<unsigned short> { enum { value = false }; };
+template <> struct hb_is_signed<unsigned int> { enum { value = false }; };
+template <> struct hb_is_signed<unsigned long> { enum { value = false }; };
+/* We need to define hb_is_signed for the typedefs we use on pre-Visual
+ * Studio 2010 for the int8_t type, since __int8/__int64 is not considered
+ * the same as char/long.  The previous lines will suffice for the other
+ * types, though.  Note that somehow, unsigned __int8 is considered same
+ * as unsigned char.
+ * https://github.com/harfbuzz/harfbuzz/pull/1499
+ */
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+template <> struct hb_is_signed<__int8> { enum { value = true }; };
+#endif
+
+template <typename T> static inline bool
+hb_in_range (T u, T lo, T hi)
+{
+  /* The sizeof() is here to force template instantiation.
+   * I'm sure there are better ways to do this but can't think of
+   * one right now.  Declaring a variable won't work as HB_UNUSED
+   * is unusable on some platforms and unused types are less likely
+   * to generate a warning than unused variables. */
+  static_assert (!hb_is_signed<T>::value, "");
+
+  /* The casts below are important as if T is smaller than int,
+   * the subtract results will become a signed int! */
+  return (T)(u - lo) <= (T)(hi - lo);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+}
+
+
+/*
+ * Sort and search.
+ */
+
+static inline void *
+hb_bsearch (const void *key, const void *base,
+           size_t nmemb, size_t size,
+           int (*compar)(const void *_key, const void *_item))
+{
+  int min = 0, max = (int) nmemb - 1;
+  while (min <= max)
+  {
+    int mid = (min + max) / 2;
+    const void *p = (const void *) (((const char *) base) + (mid * size));
+    int c = compar (key, p);
+    if (c < 0)
+      max = mid - 1;
+    else if (c > 0)
+      min = mid + 1;
+    else
+      return (void *) p;
+  }
+  return nullptr;
+}
+
 static inline void *
 hb_bsearch_r (const void *key, const void *base,
              size_t nmemb, size_t size,
@@ -39,7 +378,7 @@ hb_bsearch_r (const void *key, const void *base,
   int min = 0, max = (int) nmemb - 1;
   while (min <= max)
   {
-    int mid = (min + max) / 2;
+    int mid = ((unsigned int) min + (unsigned int) max) / 2;
     const void *p = (const void *) (((const char *) base) + (mid * size));
     int c = compar (key, p, arg);
     if (c < 0)
@@ -53,8 +392,12 @@ hb_bsearch_r (const void *key, const void *base,
 }
 
 
-
-/* From https://github.com/noporpoise/sort_r */
+/* From https://github.com/noporpoise/sort_r
+ * With following modifications:
+ *
+ * 10 November 2018:
+ * https://github.com/noporpoise/sort_r/issues/7
+ */
 
 /* Isaac Turner 29 April 2014 Public Domain */
 
@@ -110,7 +453,7 @@ static inline void sort_r_simple(void *base, size_t nel, size_t w,
 
     /* Use median of first, middle and last items as pivot */
     char *x, *y, *xend, ch;
-    char *pl, *pr;
+    char *pl, *pm, *pr;
     char *last = b+w*(nel-1), *tmp;
     char *l[3];
     l[0] = b;
@@ -132,13 +475,15 @@ static inline void sort_r_simple(void *base, size_t nel, size_t w,
     pr = last;
 
     while(pl < pr) {
-      for(; pl < pr; pl += w) {
+      pm = pl+((pr-pl+1)>>1);
+      for(; pl < pm; pl += w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pr -= w; /* pivot now at pl */
           break;
         }
       }
-      for(; pl < pr; pr -= w) {
+      pm = pl+((pr-pl)>>1);
+      for(; pm < pr; pr -= w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pl += w; /* pivot now at pr */
           break;
@@ -158,4 +503,139 @@ static inline void hb_sort_r(void *base, size_t nel, size_t width,
     sort_r_simple(base, nel, width, compar, arg);
 }
 
+
+template <typename T, typename T2> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
+{
+  for (unsigned int i = 1; i < len; i++)
+  {
+    unsigned int j = i;
+    while (j && compar (&array[j - 1], &array[i]) > 0)
+      j--;
+    if (i == j)
+      continue;
+    /* Move item i to occupy place for item j, shift what's in between. */
+    {
+      T t = array[i];
+      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
+      array[j] = t;
+    }
+    if (array2)
+    {
+      T2 t = array2[i];
+      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
+      array2[j] = t;
+    }
+  }
+}
+
+template <typename T> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
+{
+  hb_stable_sort (array, len, compar, (int *) nullptr);
+}
+
+static inline hb_bool_t
+hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
+{
+  /* Pain because we don't know whether s is nul-terminated. */
+  char buf[64];
+  len = MIN (ARRAY_LENGTH (buf) - 1, len);
+  strncpy (buf, s, len);
+  buf[len] = '\0';
+
+  char *end;
+  errno = 0;
+  unsigned long v = strtoul (buf, &end, base);
+  if (errno) return false;
+  if (*end) return false;
+  *out = v;
+  return true;
+}
+
+
+struct HbOpOr
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
+};
+struct HbOpAnd
+{
+  static constexpr bool passthru_left = false;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
+};
+struct HbOpMinus
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
+};
+struct HbOpXor
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
+};
+
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
+ * Define that to 0 to disable. */
+template <typename elt_t, unsigned int byte_size>
+struct hb_vector_size_t
+{
+  elt_t& operator [] (unsigned int i) { return u.v[i]; }
+  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+
+  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
+
+  template <class Op>
+  hb_vector_size_t process (const hb_vector_size_t &o) const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+       Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
+    else
+#endif
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+       Op::process (r.u.v[i], u.v[i], o.u.v[i]);
+    return r;
+  }
+  hb_vector_size_t operator | (const hb_vector_size_t &o) const
+  { return process<HbOpOr> (o); }
+  hb_vector_size_t operator & (const hb_vector_size_t &o) const
+  { return process<HbOpAnd> (o); }
+  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+  { return process<HbOpXor> (o); }
+  hb_vector_size_t operator ~ () const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE && 0
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+       r.u.vec[i] = ~u.vec[i];
+    else
+#endif
+    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+      r.u.v[i] = ~u.v[i];
+    return r;
+  }
+
+  private:
+  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
+  union {
+    elt_t v[byte_size / sizeof (elt_t)];
+#if HB_VECTOR_SIZE
+    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
+#endif
+  } u;
+};
+
+
 #endif /* HB_DSALGS_HH */
diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh
deleted file mode 100644 (file)
index 43e7b1c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  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
- */
-
-#ifndef HB_FACE_PRIVATE_HH
-#define HB_FACE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-
-
-/*
- * hb_face_t
- */
-
-struct hb_face_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_reference_table_func_t  reference_table_func;
-  void                      *user_data;
-  hb_destroy_func_t          destroy;
-
-  unsigned int index;                  /* Face index in a collection, zero-based. */
-  mutable unsigned int upem;           /* Units-per-EM. */
-  mutable unsigned int num_glyphs;     /* Number of glyphs. */
-
-  struct hb_shaper_data_t shaper_data; /* Various shaper data. */
-
-  /* Various non-shaping data. */
-  /* ... */
-
-  /* Cache */
-  struct plan_node_t {
-    hb_shape_plan_t *shape_plan;
-    plan_node_t *next;
-  } *shape_plans;
-
-
-  inline hb_blob_t *reference_table (hb_tag_t tag) const
-  {
-    hb_blob_t *blob;
-
-    if (unlikely (!reference_table_func))
-      return hb_blob_get_empty ();
-
-    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
-    if (unlikely (!blob))
-      return hb_blob_get_empty ();
-
-    return blob;
-  }
-
-  inline HB_PURE_FUNC unsigned int get_upem (void) const
-  {
-    if (unlikely (!upem))
-      load_upem ();
-    return upem;
-  }
-
-  inline unsigned int get_num_glyphs (void) const
-  {
-    if (unlikely (num_glyphs == (unsigned int) -1))
-      load_num_glyphs ();
-    return num_glyphs;
-  }
-
-  private:
-  HB_INTERNAL void load_upem (void) const;
-  HB_INTERNAL void load_num_glyphs (void) const;
-};
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FACE_PRIVATE_HH */
index 2fef09d..375ef92 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-face-private.hh"
-#include "hb-blob-private.hh"
-#include "hb-open-file-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-maxp-table.hh"
+#include "hb-face.hh"
+#include "hb-blob.hh"
+#include "hb-open-file.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-cmap-table.hh"
 
 
+/**
+ * SECTION:hb-face
+ * @title: hb-face
+ * @short_description: Font face objects
+ * @include: hb.h
+ *
+ * Font face is objects represent a single face in a font family.
+ * More exactly, a font face represents a single face in a binary font file.
+ * Font faces are typically built from a binary blob and a face index.
+ * Font faces are used to create fonts.
+ **/
+
 
 /**
- * hb_face_count: Get number of faces on the blob
- * @blob:
+ * hb_face_count:
+ * @blob: a blob.
  *
+ * Get number of faces in a blob.
  *
- *
- * Return value: Number of faces on the blob
+ * Return value: Number of faces in @blob
  *
  * Since: 1.7.7
  **/
@@ -52,36 +64,33 @@ hb_face_count (hb_blob_t *blob)
   if (unlikely (!blob))
     return 0;
 
-  hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
+  /* TODO We shouldn't be sanitizing blob.  Port to run sanitizer and return if not sane. */
+  /* Make API signature const after. */
+  hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
   const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
+  unsigned int ret = ot.get_face_count ();
+  hb_blob_destroy (sanitized);
 
-  return ot.get_face_count ();
+  return ret;
 }
 
 /*
  * hb_face_t
  */
 
-const hb_face_t _hb_face_nil = {
+DEFINE_NULL_INSTANCE (hb_face_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   nullptr, /* reference_table_func */
   nullptr, /* user_data */
   nullptr, /* destroy */
 
   0,    /* index */
-  1000, /* upem */
-  0,    /* num_glyphs */
+  HB_ATOMIC_INT_INIT (1000), /* upem */
+  HB_ATOMIC_INT_INIT (0),    /* num_glyphs */
 
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  },
-
-  nullptr, /* shape_plans */
+  /* Zero for the rest is fine. */
 };
 
 
@@ -114,8 +123,10 @@ hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
   face->user_data = user_data;
   face->destroy = destroy;
 
-  face->upem = 0;
-  face->num_glyphs = (unsigned int) -1;
+  face->num_glyphs.set_relaxed (-1);
+
+  face->data.init0 (face);
+  face->table.init0 (face);
 
   return face;
 }
@@ -159,11 +170,12 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
     return hb_blob_reference (data->blob);
 
   const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+  unsigned int base_offset;
+  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
 
   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
 
-  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
+  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
 
   return blob;
 }
@@ -188,7 +200,7 @@ hb_face_create (hb_blob_t    *blob,
   if (unlikely (!blob))
     blob = hb_blob_get_empty ();
 
-  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
+  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
@@ -212,9 +224,9 @@ hb_face_create (hb_blob_t    *blob,
  * Since: 0.9.2
  **/
 hb_face_t *
-hb_face_get_empty (void)
+hb_face_get_empty ()
 {
-  return const_cast<hb_face_t *> (&_hb_face_nil);
+  return const_cast<hb_face_t *> (&Null(hb_face_t));
 }
 
 
@@ -255,9 +267,8 @@ hb_face_destroy (hb_face_t *face)
     node = next;
   }
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  face->data.fini ();
+  face->table.fini ();
 
   if (face->destroy)
     face->destroy (face->user_data);
@@ -301,7 +312,7 @@ hb_face_set_user_data (hb_face_t          *face,
  * Since: 0.9.2
  **/
 void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                       hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (face, key);
@@ -318,10 +329,10 @@ hb_face_get_user_data (hb_face_t          *face,
 void
 hb_face_make_immutable (hb_face_t *face)
 {
-  if (unlikely (hb_object_is_inert (face)))
+  if (hb_object_is_immutable (face))
     return;
 
-  face->immutable = true;
+  hb_object_make_immutable (face);
 }
 
 /**
@@ -335,9 +346,9 @@ hb_face_make_immutable (hb_face_t *face)
  * Since: 0.9.2
  **/
 hb_bool_t
-hb_face_is_immutable (hb_face_t *face)
+hb_face_is_immutable (const hb_face_t *face)
 {
-  return face->immutable;
+  return hb_object_is_immutable (face);
 }
 
 
@@ -353,8 +364,8 @@ hb_face_is_immutable (hb_face_t *face)
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                        hb_tag_t   tag)
+hb_face_reference_table (const hb_face_t *face,
+                        hb_tag_t tag)
 {
   return face->reference_table (tag);
 }
@@ -388,7 +399,7 @@ void
 hb_face_set_index (hb_face_t    *face,
                   unsigned int  index)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
   face->index = index;
@@ -405,7 +416,7 @@ hb_face_set_index (hb_face_t    *face,
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_index (hb_face_t    *face)
+hb_face_get_index (const hb_face_t *face)
 {
   return face->index;
 }
@@ -423,10 +434,10 @@ void
 hb_face_set_upem (hb_face_t    *face,
                  unsigned int  upem)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->upem = upem;
+  face->upem.set_relaxed (upem);
 }
 
 /**
@@ -440,20 +451,11 @@ hb_face_set_upem (hb_face_t    *face,
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_upem (hb_face_t *face)
+hb_face_get_upem (const hb_face_t *face)
 {
   return face->get_upem ();
 }
 
-void
-hb_face_t::load_upem (void) const
-{
-  hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
-  const OT::head *head_table = head_blob->as<OT::head> ();
-  upem = head_table->get_upem ();
-  hb_blob_destroy (head_blob);
-}
-
 /**
  * hb_face_set_glyph_count:
  * @face: a face.
@@ -467,10 +469,10 @@ void
 hb_face_set_glyph_count (hb_face_t    *face,
                         unsigned int  glyph_count)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->num_glyphs = glyph_count;
+  face->num_glyphs.set_relaxed (glyph_count);
 }
 
 /**
@@ -484,23 +486,17 @@ hb_face_set_glyph_count (hb_face_t    *face,
  * Since: 0.9.7
  **/
 unsigned int
-hb_face_get_glyph_count (hb_face_t *face)
+hb_face_get_glyph_count (const hb_face_t *face)
 {
   return face->get_num_glyphs ();
 }
 
-void
-hb_face_t::load_num_glyphs (void) const
-{
-  hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
-  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
-  num_glyphs = maxp_table->get_num_glyphs ();
-  hb_blob_destroy (maxp_blob);
-}
-
 /**
  * hb_face_get_table_tags:
  * @face: a face.
+ * @start_offset: index of first tag to return.
+ * @table_count: input length of @table_tags array, output number of items written.
+ * @table_tags: array to write tags into.
  *
  * Retrieves table tags for a face, if possible.
  *
@@ -509,7 +505,7 @@ hb_face_t::load_num_glyphs (void) const
  * Since: 1.6.0
  **/
 unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                        unsigned int  start_offset,
                        unsigned int *table_count, /* IN/OUT */
                        hb_tag_t     *table_tags /* OUT */)
@@ -528,3 +524,200 @@ hb_face_get_table_tags (hb_face_t    *face,
 
   return ot_face.get_table_tags (start_offset, table_count, table_tags);
 }
+
+
+/*
+ * Character set.
+ */
+
+
+/**
+ * hb_face_collect_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters covered by @face to.
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_unicodes (hb_face_t *face,
+                         hb_set_t  *out)
+{
+  face->table.cmap->collect_unicodes (out);
+}
+
+/**
+ * hb_face_collect_variation_selectors:
+ * @face: font face.
+ * @out: set to add Variation Selector characters covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                    hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_selectors (out);
+}
+
+/**
+ * hb_face_collect_variation_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters for @variation_selector covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                   hb_codepoint_t variation_selector,
+                                   hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_unicodes (variation_selector, out);
+}
+
+
+
+/*
+ * face-builder: A face that has add_table().
+ */
+
+struct hb_face_builder_data_t
+{
+  struct table_entry_t
+  {
+    int cmp (hb_tag_t t) const
+    {
+      if (t < tag) return -1;
+      if (t > tag) return -1;
+      return 0;
+    }
+
+    hb_tag_t   tag;
+    hb_blob_t *blob;
+  };
+
+  hb_vector_t<table_entry_t> tables;
+};
+
+static hb_face_builder_data_t *
+_hb_face_builder_data_create ()
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
+  if (unlikely (!data))
+    return nullptr;
+
+  data->tables.init ();
+
+  return data;
+}
+
+static void
+_hb_face_builder_data_destroy (void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  for (unsigned int i = 0; i < data->tables.length; i++)
+    hb_blob_destroy (data->tables[i].blob);
+
+  data->tables.fini ();
+
+  free (data);
+}
+
+static hb_blob_t *
+_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
+{
+
+  unsigned int table_count = data->tables.length;
+  unsigned int face_length = table_count * 16 + 12;
+
+  for (unsigned int i = 0; i < table_count; i++)
+    face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
+
+  char *buf = (char *) malloc (face_length);
+  if (unlikely (!buf))
+    return nullptr;
+
+  hb_serialize_context_t c (buf, face_length);
+  c.propagate_error (data->tables);
+  OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
+
+  bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
+  hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+  bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
+
+  c.end_serialize ();
+
+  if (unlikely (!ret))
+  {
+    free (buf);
+    return nullptr;
+  }
+
+  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+}
+
+static hb_blob_t *
+_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  if (!tag)
+    return _hb_face_builder_data_reference_blob (data);
+
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
+  if (entry)
+    return hb_blob_reference (entry->blob);
+
+  return nullptr;
+}
+
+
+/**
+ * hb_face_builder_create:
+ *
+ * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
+ * After tables are added to the face, it can be compiled to a binary
+ * font file by calling hb_face_reference_blob().
+ *
+ * Return value: (transfer full): New face.
+ *
+ * Since: 1.9.0
+ **/
+hb_face_t *
+hb_face_builder_create ()
+{
+  hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+  if (unlikely (!data)) return hb_face_get_empty ();
+
+  return hb_face_create_for_tables (_hb_face_builder_reference_table,
+                                   data,
+                                   _hb_face_builder_data_destroy);
+}
+
+/**
+ * hb_face_builder_add_table:
+ *
+ * Add table for @tag with data provided by @blob to the face.  @face must
+ * be created using hb_face_builder_create().
+ *
+ * Since: 1.9.0
+ **/
+hb_bool_t
+hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+{
+  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+    return false;
+
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
+
+  entry->tag = tag;
+  entry->blob = hb_blob_reference (blob);
+
+  return true;
+}
index 983ee56..e8ff090 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "hb-common.h"
 #include "hb-blob.h"
+#include "hb-set.h"
 
 HB_BEGIN_DECLS
 
@@ -76,19 +77,19 @@ hb_face_set_user_data (hb_face_t          *face,
                       hb_bool_t           replace);
 
 HB_EXTERN void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                       hb_user_data_key_t *key);
 
 HB_EXTERN void
 hb_face_make_immutable (hb_face_t *face);
 
 HB_EXTERN hb_bool_t
-hb_face_is_immutable (hb_face_t *face);
+hb_face_is_immutable (const hb_face_t *face);
 
 
 HB_EXTERN hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                        hb_tag_t   tag);
+hb_face_reference_table (const hb_face_t *face,
+                        hb_tag_t tag);
 
 HB_EXTERN hb_blob_t *
 hb_face_reference_blob (hb_face_t *face);
@@ -98,28 +99,60 @@ hb_face_set_index (hb_face_t    *face,
                   unsigned int  index);
 
 HB_EXTERN unsigned int
-hb_face_get_index (hb_face_t    *face);
+hb_face_get_index (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_upem (hb_face_t    *face,
                  unsigned int  upem);
 
 HB_EXTERN unsigned int
-hb_face_get_upem (hb_face_t *face);
+hb_face_get_upem (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_glyph_count (hb_face_t    *face,
                         unsigned int  glyph_count);
 
 HB_EXTERN unsigned int
-hb_face_get_glyph_count (hb_face_t *face);
+hb_face_get_glyph_count (const hb_face_t *face);
 
 HB_EXTERN unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                        unsigned int  start_offset,
                        unsigned int *table_count, /* IN/OUT */
                        hb_tag_t     *table_tags /* OUT */);
 
+
+/*
+ * Character set.
+ */
+
+HB_EXTERN void
+hb_face_collect_unicodes (hb_face_t *face,
+                         hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                    hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                   hb_codepoint_t variation_selector,
+                                   hb_set_t  *out);
+
+
+/*
+ * Builder face.
+ */
+
+HB_EXTERN hb_face_t *
+hb_face_builder_create (void);
+
+HB_EXTERN hb_bool_t
+hb_face_builder_add_table (hb_face_t *face,
+                          hb_tag_t   tag,
+                          hb_blob_t *blob);
+
+
 HB_END_DECLS
 
 #endif /* HB_FACE_H */
diff --git a/src/hb-face.hh b/src/hb-face.hh
new file mode 100644 (file)
index 0000000..68834ba
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  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
+ */
+
+#ifndef HB_FACE_HH
+#define HB_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-ot-face.hh"
+
+
+/*
+ * hb_face_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, face);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_face_t
+{
+  hb_object_header_t header;
+
+  hb_reference_table_func_t  reference_table_func;
+  void                      *user_data;
+  hb_destroy_func_t          destroy;
+
+  unsigned int index;                  /* Face index in a collection, zero-based. */
+  mutable hb_atomic_int_t upem;                /* Units-per-EM. */
+  mutable hb_atomic_int_t num_glyphs;  /* Number of glyphs. */
+
+  hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */
+  hb_ot_face_t table;                  /* All the face's tables. */
+
+  /* Cache */
+  struct plan_node_t
+  {
+    hb_shape_plan_t *shape_plan;
+    plan_node_t *next;
+  };
+  hb_atomic_ptr_t<plan_node_t> shape_plans;
+
+  hb_blob_t *reference_table (hb_tag_t tag) const
+  {
+    hb_blob_t *blob;
+
+    if (unlikely (!reference_table_func))
+      return hb_blob_get_empty ();
+
+    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
+    if (unlikely (!blob))
+      return hb_blob_get_empty ();
+
+    return blob;
+  }
+
+  HB_PURE_FUNC unsigned int get_upem () const
+  {
+    unsigned int ret = upem.get_relaxed ();
+    if (unlikely (!ret))
+    {
+      return load_upem ();
+    }
+    return ret;
+  }
+
+  unsigned int get_num_glyphs () const
+  {
+    unsigned int ret = num_glyphs.get_relaxed ();
+    if (unlikely (ret == (unsigned int) -1))
+      return load_num_glyphs ();
+    return ret;
+  }
+
+  private:
+  HB_INTERNAL unsigned int load_upem () const;
+  HB_INTERNAL unsigned int load_num_glyphs () const;
+};
+DECLARE_NULL_INSTANCE (hb_face_t);
+
+
+#endif /* HB_FACE_HH */
index 3f09c3f..09f0290 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER fallback
-#include "hb-shaper-impl-private.hh"
-
-
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
+#include "hb-shaper-impl.hh"
 
 
 /*
  * shaper face data
  */
 
-struct hb_fallback_shaper_face_data_t {};
+struct hb_fallback_face_data_t {};
 
-hb_fallback_shaper_face_data_t *
+hb_fallback_face_data_t *
 _hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
 {
-  return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
+_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -54,38 +49,16 @@ _hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_U
  * shaper font data
  */
 
-struct hb_fallback_shaper_font_data_t {};
+struct hb_fallback_font_data_t {};
 
-hb_fallback_shaper_font_data_t *
+hb_fallback_font_data_t *
 _hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_fallback_shaper_shape_plan_data_t {};
-
-hb_fallback_shaper_shape_plan_data_t *
-_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                           const hb_feature_t *user_features HB_UNUSED,
-                                           unsigned int        num_user_features HB_UNUSED,
-                                           const int          *coords HB_UNUSED,
-                                           unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
 {
 }
 
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
deleted file mode 100644 (file)
index 7ba16cd..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  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
- */
-
-#ifndef HB_FONT_PRIVATE_HH
-#define HB_FONT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-face-private.hh"
-#include "hb-shaper-private.hh"
-
-
-
-/*
- * hb_font_funcs_t
- */
-
-#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
-  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
-  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-  /* ^--- Add new callbacks here */
-
-struct hb_font_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } destroy;
-
-  /* Don't access these directly.  Call font->get_*() instead. */
-  union get_t {
-    struct get_funcs_t {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    } f;
-    void (*array[0
-#define HB_FONT_FUNC_IMPLEMENT(name) +1
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-               ]) (void);
-  } get;
-};
-
-
-
-/*
- * hb_font_t
- */
-
-struct hb_font_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_font_t *parent;
-  hb_face_t *face;
-
-  int x_scale;
-  int y_scale;
-
-  unsigned int x_ppem;
-  unsigned int y_ppem;
-
-  float ptem;
-
-  /* Font variation coordinates. */
-  unsigned int num_coords;
-  int *coords;
-
-  hb_font_funcs_t   *klass;
-  void              *user_data;
-  hb_destroy_func_t  destroy;
-
-  struct hb_shaper_data_t shaper_data;
-
-
-  /* Convert from font-space to user-space */
-  inline int dir_scale (hb_direction_t direction)
-  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
-  inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
-  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
-  inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
-  inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
-  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v, dir_scale (direction)); }
-
-  /* Convert from parent-font user-space to our user-space */
-  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
-    if (unlikely (parent && parent->x_scale != x_scale))
-      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
-    if (unlikely (parent && parent->y_scale != y_scale))
-      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_x_position (hb_position_t v) {
-    return parent_scale_x_distance (v);
-  }
-  inline hb_position_t parent_scale_y_position (hb_position_t v) {
-    return parent_scale_y_distance (v);
-  }
-
-  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_distance (*x);
-    *y = parent_scale_y_distance (*y);
-  }
-  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_position (*x);
-    *y = parent_scale_y_position (*y);
-  }
-
-
-  /* Public getters */
-
-  HB_INTERNAL bool has_func (unsigned int i);
-
-  /* has_* ... */
-#define HB_FONT_FUNC_IMPLEMENT(name) \
-  bool \
-  has_##name##_func (void) \
-  { \
-    hb_font_funcs_t *funcs = this->klass; \
-    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
-    return has_func (i); \
-  }
-  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_h_extents (this, user_data,
-                                       extents,
-                                       klass->user_data.font_h_extents);
-  }
-  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_v_extents (this, user_data,
-                                       extents,
-                                       klass->user_data.font_v_extents);
-  }
-
-  inline bool has_glyph (hb_codepoint_t unicode)
-  {
-    hb_codepoint_t glyph;
-    return get_nominal_glyph (unicode, &glyph);
-  }
-
-  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-                                     hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.nominal_glyph (this, user_data,
-                                      unicode, glyph,
-                                      klass->user_data.nominal_glyph);
-  }
-
-  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-                                       hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.variation_glyph (this, user_data,
-                                        unicode, variation_selector, glyph,
-                                        klass->user_data.variation_glyph);
-  }
-
-  inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_h_advance (this, user_data,
-                                        glyph,
-                                        klass->user_data.glyph_h_advance);
-  }
-
-  inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_v_advance (this, user_data,
-                                        glyph,
-                                        klass->user_data.glyph_v_advance);
-  }
-
-  inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
-                                      hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_h_origin (this, user_data,
-                                       glyph, x, y,
-                                       klass->user_data.glyph_h_origin);
-  }
-
-  inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
-                                      hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_v_origin (this, user_data,
-                                       glyph, x, y,
-                                       klass->user_data.glyph_v_origin);
-  }
-
-  inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
-  {
-    return klass->get.f.glyph_h_kerning (this, user_data,
-                                        left_glyph, right_glyph,
-                                        klass->user_data.glyph_h_kerning);
-  }
-
-  inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
-  {
-    return klass->get.f.glyph_v_kerning (this, user_data,
-                                        top_glyph, bottom_glyph,
-                                        klass->user_data.glyph_v_kerning);
-  }
-
-  inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
-                                     hb_glyph_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.glyph_extents (this, user_data,
-                                      glyph,
-                                      extents,
-                                      klass->user_data.glyph_extents);
-  }
-
-  inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
-                                           hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_contour_point (this, user_data,
-                                            glyph, point_index,
-                                            x, y,
-                                            klass->user_data.glyph_contour_point);
-  }
-
-  inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
-                                  char *name, unsigned int size)
-  {
-    if (size) *name = '\0';
-    return klass->get.f.glyph_name (this, user_data,
-                                   glyph,
-                                   name, size,
-                                   klass->user_data.glyph_name);
-  }
-
-  inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
-                                       hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    if (len == -1) len = strlen (name);
-    return klass->get.f.glyph_from_name (this, user_data,
-                                        name, len,
-                                        glyph,
-                                        klass->user_data.glyph_from_name);
-  }
-
-
-  /* A bit higher-level, and with fallback */
-
-  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_h_extents (extents))
-    {
-      extents->ascender = y_scale * .8;
-      extents->descender = extents->ascender - y_scale;
-      extents->line_gap = 0;
-    }
-  }
-  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_v_extents (extents))
-    {
-      extents->ascender = x_scale / 2;
-      extents->descender = extents->ascender - x_scale;
-      extents->line_gap = 0;
-    }
-  }
-
-  inline void get_extents_for_direction (hb_direction_t direction,
-                                        hb_font_extents_t *extents)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_h_extents_with_fallback (extents);
-    else
-      get_v_extents_with_fallback (extents);
-  }
-
-  inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_advance (glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_advance (glyph);
-    }
-  }
-
-  inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
-                                            hb_position_t *x, hb_position_t *y)
-  {
-    *x = get_glyph_h_advance (glyph) / 2;
-
-    /* TODO cache this somehow?! */
-    hb_font_extents_t extents;
-    get_h_extents_with_fallback (&extents);
-    *y = extents.ascender;
-  }
-
-  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_h_origin (glyph, x, y) &&
-        get_glyph_v_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x -= dx; *y -= dy;
-    }
-  }
-  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_v_origin (glyph, x, y) &&
-        get_glyph_h_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x += dx; *y += dy;
-    }
-  }
-
-  inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                             hb_direction_t direction,
-                                             hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_glyph_h_origin_with_fallback (glyph, x, y);
-    else
-      get_glyph_v_origin_with_fallback (glyph, x, y);
-  }
-
-  inline void add_glyph_h_origin (hb_codepoint_t glyph,
-                                 hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_v_origin (hb_codepoint_t glyph,
-                                 hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                             hb_direction_t direction,
-                                             hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-
-  inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
-                                      hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
-                                      hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                                  hb_direction_t direction,
-                                                  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-
-  inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_kerning (first_glyph, second_glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_kerning (first_glyph, second_glyph);
-    }
-  }
-
-  inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
-                                                hb_direction_t direction,
-                                                hb_glyph_extents_t *extents)
-  {
-    hb_bool_t ret = get_glyph_extents (glyph, extents);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
-
-    return ret;
-  }
-
-  inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
-                                                      hb_direction_t direction,
-                                                      hb_position_t *x, hb_position_t *y)
-  {
-    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, x, y);
-
-    return ret;
-  }
-
-  /* Generates gidDDD if glyph has no name. */
-  inline void
-  glyph_to_string (hb_codepoint_t glyph,
-                  char *s, unsigned int size)
-  {
-    if (get_glyph_name (glyph, s, size)) return;
-
-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
-      *s = '\0';
-  }
-
-  /* Parses gidDDD and uniUUUU strings automatically. */
-  inline hb_bool_t
-  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
-                    hb_codepoint_t *glyph)
-  {
-    if (get_glyph_from_name (s, len, glyph)) return true;
-
-    if (len == -1) len = strlen (s);
-
-    /* Straight glyph index. */
-    if (hb_codepoint_parse (s, len, 10, glyph))
-      return true;
-
-    if (len > 3)
-    {
-      /* gidDDD syntax for glyph indices. */
-      if (0 == strncmp (s, "gid", 3) &&
-         hb_codepoint_parse (s + 3, len - 3, 10, glyph))
-       return true;
-
-      /* uniUUUU and other Unicode character indices. */
-      hb_codepoint_t unichar;
-      if (0 == strncmp (s, "uni", 3) &&
-         hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
-         get_nominal_glyph (unichar, glyph))
-       return true;
-    }
-
-    return false;
-  }
-
-  inline hb_position_t em_scale (int16_t v, int scale)
-  {
-    int upem = face->get_upem ();
-    int64_t scaled = v * (int64_t) scale;
-    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
-    return (hb_position_t) (scaled / upem);
-  }
-  inline hb_position_t em_scalef (float v, int scale)
-  {
-    return (hb_position_t) round (v * scale / face->get_upem ());
-  }
-  inline float em_fscale (int16_t v, int scale)
-  {
-    return (float) v * scale / face->get_upem ();
-  }
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FONT_PRIVATE_HH */
index 4d62b9e..817a1a7 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
+#include "hb-ot.h"
+
+
+/**
+ * SECTION:hb-font
+ * @title: hb-font
+ * @short_description: Font objects
+ * @include: hb.h
+ *
+ * Font objects represent a font face at a certain size and other
+ * parameters (pixels per EM, points per EM, variation settings.)
+ * Fonts are created from font faces, and are used as input to
+ * hb_shape() among other things.
+ **/
 
 
 /*
 static hb_bool_t
 hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_font_extents_t *metrics,
+                               hb_font_extents_t *extents,
                                void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_h_extents_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_font_extents_t *metrics,
-                                  void *user_data HB_UNUSED)
+hb_font_get_font_h_extents_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_font_extents_t *extents,
+                                   void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_h_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_h_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_y_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_y_distance (extents->ascender);
+    extents->descender = font->parent_scale_y_distance (extents->descender);
+    extents->line_gap = font->parent_scale_y_distance (extents->line_gap);
   }
   return ret;
 }
@@ -62,23 +78,23 @@ hb_font_get_font_h_extents_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_font_extents_t *metrics,
+                               hb_font_extents_t *extents,
                                void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_v_extents_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_font_extents_t *metrics,
-                                  void *user_data HB_UNUSED)
+hb_font_get_font_v_extents_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_font_extents_t *extents,
+                                   void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_v_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_v_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_x_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_x_distance (extents->ascender);
+    extents->descender = font->parent_scale_x_distance (extents->descender);
+    extents->line_gap = font->parent_scale_x_distance (extents->line_gap);
   }
   return ret;
 }
@@ -86,7 +102,7 @@ hb_font_get_font_v_extents_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
                               void *font_data HB_UNUSED,
-                              hb_codepoint_t unicode,
+                              hb_codepoint_t unicode HB_UNUSED,
                               hb_codepoint_t *glyph,
                               void *user_data HB_UNUSED)
 {
@@ -94,20 +110,53 @@ hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_nominal_glyph_parent (hb_font_t *font,
-                                 void *font_data HB_UNUSED,
-                                 hb_codepoint_t unicode,
-                                 hb_codepoint_t *glyph,
-                                 void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_default (hb_font_t *font,
+                                  void *font_data HB_UNUSED,
+                                  hb_codepoint_t unicode,
+                                  hb_codepoint_t *glyph,
+                                  void *user_data HB_UNUSED)
 {
+  if (font->has_nominal_glyphs_func_set ())
+  {
+    return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0);
+  }
   return font->parent->get_nominal_glyph (unicode, glyph);
 }
 
+#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default
+static unsigned int
+hb_font_get_nominal_glyphs_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   unsigned int count,
+                                   const hb_codepoint_t *first_unicode,
+                                   unsigned int unicode_stride,
+                                   hb_codepoint_t *first_glyph,
+                                   unsigned int glyph_stride,
+                                   void *user_data HB_UNUSED)
+{
+  if (font->has_nominal_glyph_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!font->get_nominal_glyph (*first_unicode, first_glyph))
+       return i;
+
+      first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    }
+    return count;
+  }
+
+  return font->parent->get_nominal_glyphs (count,
+                                          first_unicode, unicode_stride,
+                                          first_glyph, glyph_stride);
+}
+
 static hb_bool_t
 hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t unicode,
-                                hb_codepoint_t variation_selector,
+                                hb_codepoint_t unicode HB_UNUSED,
+                                hb_codepoint_t variation_selector HB_UNUSED,
                                 hb_codepoint_t *glyph,
                                 void *user_data HB_UNUSED)
 {
@@ -115,12 +164,12 @@ hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_variation_glyph_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t unicode,
-                                   hb_codepoint_t variation_selector,
-                                   hb_codepoint_t *glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_variation_glyph_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t unicode,
+                                    hb_codepoint_t variation_selector,
+                                    hb_codepoint_t *glyph,
+                                    void *user_data HB_UNUSED)
 {
   return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
 }
@@ -129,42 +178,118 @@ hb_font_get_variation_glyph_parent (hb_font_t *font,
 static hb_position_t
 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 void *user_data HB_UNUSED)
 {
   return font->x_scale;
 }
 static hb_position_t
-hb_font_get_glyph_h_advance_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_h_advance_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    void *user_data HB_UNUSED)
 {
+  if (font->has_glyph_h_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
   return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
 }
 
 static hb_position_t
 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 void *user_data HB_UNUSED)
 {
   /* TODO use font_extents.ascender+descender */
   return font->y_scale;
 }
 static hb_position_t
-hb_font_get_glyph_v_advance_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_v_advance_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    void *user_data HB_UNUSED)
 {
+  if (font->has_glyph_v_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
   return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
 }
 
+#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
+static void
+hb_font_get_glyph_h_advances_default (hb_font_t* font,
+                                     void* font_data HB_UNUSED,
+                                     unsigned int count,
+                                     const hb_codepoint_t *first_glyph,
+                                     unsigned int glyph_stride,
+                                     hb_position_t *first_advance,
+                                     unsigned int advance_stride,
+                                     void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_h_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_h_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_h_advances (count,
+                                     first_glyph, glyph_stride,
+                                     first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_x_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
+}
+
+#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default
+static void
+hb_font_get_glyph_v_advances_default (hb_font_t* font,
+                                     void* font_data HB_UNUSED,
+                                     unsigned int count,
+                                     const hb_codepoint_t *first_glyph,
+                                     unsigned int glyph_stride,
+                                     hb_position_t *first_advance,
+                                     unsigned int advance_stride,
+                                     void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_v_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_v_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_v_advances (count,
+                                     first_glyph, glyph_stride,
+                                     first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_y_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
+}
+
 static hb_bool_t
 hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
+                               hb_codepoint_t glyph HB_UNUSED,
                                hb_position_t *x,
                                hb_position_t *y,
                                void *user_data HB_UNUSED)
@@ -173,12 +298,12 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
   return true;
 }
 static hb_bool_t
-hb_font_get_glyph_h_origin_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t glyph,
-                                  hb_position_t *x,
-                                  hb_position_t *y,
-                                  void *user_data HB_UNUSED)
+hb_font_get_glyph_h_origin_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t glyph,
+                                   hb_position_t *x,
+                                   hb_position_t *y,
+                                   void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
   if (ret)
@@ -189,7 +314,7 @@ hb_font_get_glyph_h_origin_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
+                               hb_codepoint_t glyph HB_UNUSED,
                                hb_position_t *x,
                                hb_position_t *y,
                                void *user_data HB_UNUSED)
@@ -198,12 +323,12 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_v_origin_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t glyph,
-                                  hb_position_t *x,
-                                  hb_position_t *y,
-                                  void *user_data HB_UNUSED)
+hb_font_get_glyph_v_origin_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t glyph,
+                                   hb_position_t *x,
+                                   hb_position_t *y,
+                                   void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
   if (ret)
@@ -214,18 +339,18 @@ hb_font_get_glyph_v_origin_parent (hb_font_t *font,
 static hb_position_t
 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t left_glyph,
-                                hb_codepoint_t right_glyph,
+                                hb_codepoint_t left_glyph HB_UNUSED,
+                                hb_codepoint_t right_glyph HB_UNUSED,
                                 void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t left_glyph,
-                                   hb_codepoint_t right_glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_h_kerning_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t left_glyph,
+                                    hb_codepoint_t right_glyph,
+                                    void *user_data HB_UNUSED)
 {
   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 }
@@ -233,18 +358,18 @@ hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
 static hb_position_t
 hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t top_glyph,
-                                hb_codepoint_t bottom_glyph,
+                                hb_codepoint_t top_glyph HB_UNUSED,
+                                hb_codepoint_t bottom_glyph HB_UNUSED,
                                 void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t top_glyph,
-                                   hb_codepoint_t bottom_glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_v_kerning_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t top_glyph,
+                                    hb_codepoint_t bottom_glyph,
+                                    void *user_data HB_UNUSED)
 {
   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 }
@@ -252,7 +377,7 @@ hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
                               void *font_data HB_UNUSED,
-                              hb_codepoint_t glyph,
+                              hb_codepoint_t glyph HB_UNUSED,
                               hb_glyph_extents_t *extents,
                               void *user_data HB_UNUSED)
 {
@@ -260,11 +385,11 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_extents_parent (hb_font_t *font,
-                                 void *font_data HB_UNUSED,
-                                 hb_codepoint_t glyph,
-                                 hb_glyph_extents_t *extents,
-                                 void *user_data HB_UNUSED)
+hb_font_get_glyph_extents_default (hb_font_t *font,
+                                  void *font_data HB_UNUSED,
+                                  hb_codepoint_t glyph,
+                                  hb_glyph_extents_t *extents,
+                                  void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
   if (ret) {
@@ -277,8 +402,8 @@ hb_font_get_glyph_extents_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
                                     void *font_data HB_UNUSED,
-                                    hb_codepoint_t glyph,
-                                    unsigned int point_index,
+                                    hb_codepoint_t glyph HB_UNUSED,
+                                    unsigned int point_index HB_UNUSED,
                                     hb_position_t *x,
                                     hb_position_t *y,
                                     void *user_data HB_UNUSED)
@@ -287,13 +412,13 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_contour_point_parent (hb_font_t *font,
-                                       void *font_data HB_UNUSED,
-                                       hb_codepoint_t glyph,
-                                       unsigned int point_index,
-                                       hb_position_t *x,
-                                       hb_position_t *y,
-                                       void *user_data HB_UNUSED)
+hb_font_get_glyph_contour_point_default (hb_font_t *font,
+                                        void *font_data HB_UNUSED,
+                                        hb_codepoint_t glyph,
+                                        unsigned int point_index,
+                                        hb_position_t *x,
+                                        hb_position_t *y,
+                                        void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
   if (ret)
@@ -304,7 +429,7 @@ hb_font_get_glyph_contour_point_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
                            void *font_data HB_UNUSED,
-                           hb_codepoint_t glyph,
+                           hb_codepoint_t glyph HB_UNUSED,
                            char *name, unsigned int size,
                            void *user_data HB_UNUSED)
 {
@@ -312,11 +437,11 @@ hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_name_parent (hb_font_t *font,
-                              void *font_data HB_UNUSED,
-                              hb_codepoint_t glyph,
-                              char *name, unsigned int size,
-                              void *user_data HB_UNUSED)
+hb_font_get_glyph_name_default (hb_font_t *font,
+                               void *font_data HB_UNUSED,
+                               hb_codepoint_t glyph,
+                               char *name, unsigned int size,
+                               void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_name (glyph, name, size);
 }
@@ -324,7 +449,8 @@ hb_font_get_glyph_name_parent (hb_font_t *font,
 static hb_bool_t
 hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                const char *name, int len, /* -1 means nul-terminated */
+                                const char *name HB_UNUSED,
+                                int len HB_UNUSED, /* -1 means nul-terminated */
                                 hb_codepoint_t *glyph,
                                 void *user_data HB_UNUSED)
 {
@@ -332,20 +458,19 @@ hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_from_name_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   const char *name, int len, /* -1 means nul-terminated */
-                                   hb_codepoint_t *glyph,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_from_name_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    const char *name, int len, /* -1 means nul-terminated */
+                                    hb_codepoint_t *glyph,
+                                    void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_from_name (name, len, glyph);
 }
 
-static const hb_font_funcs_t _hb_font_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -364,10 +489,9 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
     }
   }
 };
-static const hb_font_funcs_t _hb_font_funcs_parent = {
-  HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
+static const hb_font_funcs_t _hb_font_funcs_default = {
+  HB_OBJECT_HEADER_STATIC,
 
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
@@ -381,7 +505,7 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
   },
   {
     {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
     }
@@ -399,14 +523,14 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_create (void)
+hb_font_funcs_create ()
 {
   hb_font_funcs_t *ffuncs;
 
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return hb_font_funcs_get_empty ();
 
-  ffuncs->get = _hb_font_funcs_parent.get;
+  ffuncs->get = _hb_font_funcs_default.get;
 
   return ffuncs;
 }
@@ -421,9 +545,9 @@ hb_font_funcs_create (void)
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_get_empty (void)
+hb_font_funcs_get_empty ()
 {
-  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
+  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
 }
 
 /**
@@ -517,10 +641,10 @@ hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
-  if (unlikely (hb_object_is_inert (ffuncs)))
+  if (hb_object_is_immutable (ffuncs))
     return;
 
-  ffuncs->immutable = true;
+  hb_object_make_immutable (ffuncs);
 }
 
 /**
@@ -536,7 +660,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 {
-  return ffuncs->immutable;
+  return hb_object_is_immutable (ffuncs);
 }
 
 
@@ -548,7 +672,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
                                  void                        *user_data, \
                                  hb_destroy_func_t            destroy)   \
 {                                                                        \
-  if (ffuncs->immutable) {                                               \
+  if (hb_object_is_immutable (ffuncs)) {                                 \
     if (destroy)                                                         \
       destroy (user_data);                                               \
     return;                                                              \
@@ -562,9 +686,9 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
     ffuncs->user_data.name = user_data;                                  \
     ffuncs->destroy.name = destroy;                                      \
   } else {                                                               \
-    ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
-    ffuncs->user_data.name = nullptr;                                       \
-    ffuncs->destroy.name = nullptr;                                         \
+    ffuncs->get.f.name = hb_font_get_##name##_default;                   \
+    ffuncs->user_data.name = nullptr;                                    \
+    ffuncs->destroy.name = nullptr;                                      \
   }                                                                      \
 }
 
@@ -572,11 +696,16 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
 
 bool
+hb_font_t::has_func_set (unsigned int i)
+{
+  return this->klass->get.array[i] != _hb_font_funcs_default.get.array[i];
+}
+
+bool
 hb_font_t::has_func (unsigned int i)
 {
-  if (parent && parent != hb_font_get_empty () && parent->has_func (i))
-    return true;
-  return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
+  return has_func_set (i) ||
+        (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
 }
 
 /* Public getters */
@@ -718,6 +847,43 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
 }
 
 /**
+ * hb_font_get_glyph_h_advances:
+ * @font: a font.
+ *
+ * 
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                             unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned advance_stride)
+{
+  font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+/**
+ * hb_font_get_glyph_v_advances:
+ * @font: a font.
+ *
+ * 
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                             unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned advance_stride)
+{
+  font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+
+/**
  * hb_font_get_glyph_h_origin:
  * @font: a font.
  * @glyph: 
@@ -770,6 +936,7 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
  * Return value: 
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
@@ -789,6 +956,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font,
  * Return value: 
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
@@ -888,7 +1056,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
  * hb_font_get_extents_for_direction:
  * @font: a font.
  * @direction:
- * @extents:
+ * @extents: (out):
  *
  *
  *
@@ -921,6 +1089,26 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
 {
   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 }
+/**
+ * hb_font_get_glyph_advances_for_direction:
+ * @font: a font.
+ * @direction: 
+ *
+ * 
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                         hb_direction_t direction,
+                                         unsigned int count,
+                                         const hb_codepoint_t *first_glyph,
+                                         unsigned glyph_stride,
+                                         hb_position_t *first_advance,
+                                         unsigned advance_stride)
+{
+  font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
 
 /**
  * hb_font_get_glyph_origin_for_direction:
@@ -997,6 +1185,7 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
  * 
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
@@ -1100,6 +1289,49 @@ hb_font_glyph_from_string (hb_font_t *font,
  * hb_font_t
  */
 
+DEFINE_NULL_INSTANCE (hb_font_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  nullptr, /* parent */
+  const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
+
+  1000, /* x_scale */
+  1000, /* y_scale */
+
+  0, /* x_ppem */
+  0, /* y_ppem */
+  0, /* ptem */
+
+  0, /* num_coords */
+  nullptr, /* coords */
+
+  const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
+
+  /* Zero for the rest is fine. */
+};
+
+
+static hb_font_t *
+_hb_font_create (hb_face_t *face)
+{
+  hb_font_t *font;
+
+  if (unlikely (!face))
+    face = hb_face_get_empty ();
+  if (!(font = hb_object_create<hb_font_t> ()))
+    return hb_font_get_empty ();
+
+  hb_face_make_immutable (face);
+  font->parent = hb_font_get_empty ();
+  font->face = hb_face_reference (face);
+  font->klass = hb_font_funcs_get_empty ();
+  font->data.init0 (font);
+  font->x_scale = font->y_scale = hb_face_get_upem (face);
+
+  return font;
+}
+
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
@@ -1113,19 +1345,10 @@ hb_font_glyph_from_string (hb_font_t *font,
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
-  hb_font_t *font;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-  if (!(font = hb_object_create<hb_font_t> ()))
-    return hb_font_get_empty ();
+  hb_font_t *font = _hb_font_create (face);
 
-  hb_face_make_immutable (face);
-  font->parent = hb_font_get_empty ();
-  font->face = hb_face_reference (face);
-  font->klass = hb_font_funcs_get_empty ();
-
-  font->x_scale = font->y_scale = hb_face_get_upem (face);
+  /* Install our in-house, very lightweight, funcs. */
+  hb_ot_font_set_funcs (font);
 
   return font;
 }
@@ -1146,9 +1369,9 @@ hb_font_create_sub_font (hb_font_t *parent)
   if (unlikely (!parent))
     parent = hb_font_get_empty ();
 
-  hb_font_t *font = hb_font_create (parent->face);
+  hb_font_t *font = _hb_font_create (parent->face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   font->parent = hb_font_reference (parent);
@@ -1185,38 +1408,9 @@ hb_font_create_sub_font (hb_font_t *parent)
  * Since: 0.9.2
  **/
 hb_font_t *
-hb_font_get_empty (void)
+hb_font_get_empty ()
 {
-  static const hb_font_t _hb_font_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* parent */
-    const_cast<hb_face_t *> (&_hb_face_nil),
-
-    1000, /* x_scale */
-    1000, /* y_scale */
-
-    0, /* x_ppem */
-    0, /* y_ppem */
-    0, /* ptem */
-
-    0, /* num_coords */
-    nullptr, /* coords */
-
-    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
-    nullptr, /* user_data */
-    nullptr, /* destroy */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_font_t *> (&_hb_font_nil);
+  return const_cast<hb_font_t *> (&Null(hb_font_t));
 }
 
 /**
@@ -1248,9 +1442,7 @@ hb_font_destroy (hb_font_t *font)
 {
   if (!hb_object_destroy (font)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  font->data.fini ();
 
   if (font->destroy)
     font->destroy (font->user_data);
@@ -1317,13 +1509,13 @@ hb_font_get_user_data (hb_font_t          *font,
 void
 hb_font_make_immutable (hb_font_t *font)
 {
-  if (unlikely (hb_object_is_inert (font)))
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->parent)
     hb_font_make_immutable (font->parent);
 
-  font->immutable = true;
+  hb_object_make_immutable (font);
 }
 
 /**
@@ -1339,7 +1531,7 @@ hb_font_make_immutable (hb_font_t *font)
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font)
 {
-  return font->immutable;
+  return hb_object_is_immutable (font);
 }
 
 /**
@@ -1355,7 +1547,7 @@ void
 hb_font_set_parent (hb_font_t *font,
                    hb_font_t *parent)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!parent)
@@ -1397,7 +1589,7 @@ void
 hb_font_set_face (hb_font_t *font,
                  hb_face_t *face)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (unlikely (!face))
@@ -1444,7 +1636,8 @@ hb_font_set_funcs (hb_font_t         *font,
                   void              *font_data,
                   hb_destroy_func_t  destroy)
 {
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1479,7 +1672,8 @@ hb_font_set_funcs_data (hb_font_t         *font,
                        hb_destroy_func_t  destroy)
 {
   /* Destroy user_data? */
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1508,7 +1702,7 @@ hb_font_set_scale (hb_font_t *font,
                   int x_scale,
                   int y_scale)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_scale = x_scale;
@@ -1549,7 +1743,7 @@ hb_font_set_ppem (hb_font_t *font,
                  unsigned int x_ppem,
                  unsigned int y_ppem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_ppem = x_ppem;
@@ -1578,16 +1772,18 @@ hb_font_get_ppem (hb_font_t *font,
 /**
  * hb_font_set_ptem:
  * @font: a font.
- * @ptem: 
+ * @ptem: font size in points.
  *
- * Sets "point size" of the font.
+ * Sets "point size" of the font.  Set to 0 to unset.
+ *
+ * There are 72 points in an inch.
  *
  * Since: 1.6.0
  **/
 void
 hb_font_set_ptem (hb_font_t *font, float ptem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->ptem = ptem;
@@ -1634,7 +1830,7 @@ hb_font_set_variations (hb_font_t *font,
                        const hb_variation_t *variations,
                        unsigned int variations_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!variations_length)
@@ -1665,7 +1861,7 @@ hb_font_set_var_coords_design (hb_font_t *font,
                               const float *coords,
                               unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
@@ -1686,7 +1882,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
                                   const int *coords, /* 2.14 normalized */
                                   unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
@@ -1718,8 +1914,6 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
 }
 
 
-#ifndef HB_DISABLE_DEPRECATED
-
 /*
  * Deprecated get_glyph_func():
  */
@@ -1806,9 +2000,9 @@ hb_font_get_variation_glyph_trampoline (hb_font_t *font,
 /**
  * hb_font_funcs_set_glyph_func:
  * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @func: (closure user_data) (destroy destroy) (scope notified): callback function.
+ * @user_data: data to pass to @func.
+ * @destroy: function to call when @user_data is not needed anymore.
  *
  * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
  * hb_font_funcs_set_variation_glyph_func() instead.
@@ -1842,5 +2036,3 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
                                          trampoline,
                                          trampoline_destroy);
 }
-
-#endif /* HB_DISABLE_DEPRECATED */
index c95b61d..e2086d8 100644 (file)
@@ -110,7 +110,7 @@ typedef struct hb_glyph_extents_t
 /* func types */
 
 typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
-                                                      hb_font_extents_t *metrics,
+                                                      hb_font_extents_t *extents,
                                                       void *user_data);
 typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
 typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
@@ -125,6 +125,14 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *
                                                         hb_codepoint_t *glyph,
                                                         void *user_data);
 
+typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data,
+                                                          unsigned int count,
+                                                          const hb_codepoint_t *first_unicode,
+                                                          unsigned int unicode_stride,
+                                                          hb_codepoint_t *first_glyph,
+                                                          unsigned int glyph_stride,
+                                                          void *user_data);
+
 
 typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
                                                           hb_codepoint_t glyph,
@@ -132,6 +140,16 @@ typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
 
+typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
+                                                  unsigned int count,
+                                                  const hb_codepoint_t *first_glyph,
+                                                  unsigned glyph_stride,
+                                                  hb_position_t *first_advance,
+                                                  unsigned advance_stride,
+                                                  void *user_data);
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
+
 typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
                                                      hb_codepoint_t glyph,
                                                      hb_position_t *x, hb_position_t *y,
@@ -139,12 +157,6 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
 
-typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-                                                          hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                                          void *user_data);
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
-
 
 typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
                                                       hb_codepoint_t glyph,
@@ -217,6 +229,22 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
                                      void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_nominal_glyphs_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
+                                      hb_font_get_nominal_glyphs_func_t func,
+                                      void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_variation_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -265,7 +293,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
                                        void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_h_origin_func:
+ * hb_font_funcs_set_glyph_h_advances_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
@@ -273,15 +301,15 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
  *
  * 
  *
- * Since: 0.9.2
+ * Since: 1.8.6
  **/
 HB_EXTERN void
-hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
-                                      hb_font_get_glyph_h_origin_func_t func,
-                                      void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_glyph_h_advances_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_v_origin_func:
+ * hb_font_funcs_set_glyph_v_advances_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
@@ -289,15 +317,15 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
  *
  * 
  *
- * Since: 0.9.2
+ * Since: 1.8.6
  **/
 HB_EXTERN void
-hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
-                                      hb_font_get_glyph_v_origin_func_t func,
-                                      void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_glyph_v_advances_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_h_kerning_func:
+ * hb_font_funcs_set_glyph_h_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
@@ -308,12 +336,12 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
  * Since: 0.9.2
  **/
 HB_EXTERN void
-hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-                                       hb_font_get_glyph_h_kerning_func_t func,
-                                       void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
+                                      hb_font_get_glyph_h_origin_func_t func,
+                                      void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_v_kerning_func:
+ * hb_font_funcs_set_glyph_v_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
  * @user_data:
@@ -324,9 +352,9 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
  * Since: 0.9.2
  **/
 HB_EXTERN void
-hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
-                                       hb_font_get_glyph_v_kerning_func_t func,
-                                       void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
+                                      hb_font_get_glyph_v_origin_func_t func,
+                                      void *user_data, hb_destroy_func_t destroy);
 
 /**
  * hb_font_funcs_set_glyph_extents_func:
@@ -417,6 +445,21 @@ HB_EXTERN hb_position_t
 hb_font_get_glyph_v_advance (hb_font_t *font,
                             hb_codepoint_t glyph);
 
+HB_EXTERN void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                             unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned advance_stride);
+HB_EXTERN void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                             unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned advance_stride);
+
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
                            hb_codepoint_t glyph,
@@ -426,13 +469,6 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
                            hb_codepoint_t glyph,
                            hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-                            hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-HB_EXTERN hb_position_t
-hb_font_get_glyph_v_kerning (hb_font_t *font,
-                            hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
                           hb_codepoint_t glyph,
@@ -472,6 +508,14 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
                                         hb_direction_t direction,
                                         hb_position_t *x, hb_position_t *y);
 HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                         hb_direction_t direction,
+                                         unsigned int count,
+                                         const hb_codepoint_t *first_glyph,
+                                         unsigned glyph_stride,
+                                         hb_position_t *first_advance,
+                                         unsigned advance_stride);
+HB_EXTERN void
 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
                                        hb_codepoint_t glyph,
                                        hb_direction_t direction,
@@ -487,12 +531,6 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
                                             hb_direction_t direction,
                                             hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-                                        hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                        hb_direction_t direction,
-                                        hb_position_t *x, hb_position_t *y);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
                                      hb_codepoint_t glyph,
diff --git a/src/hb-font.hh b/src/hb-font.hh
new file mode 100644 (file)
index 0000000..aaa0fd9
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  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
+ */
+
+#ifndef HB_FONT_HH
+#define HB_FONT_HH
+
+#include "hb.hh"
+
+#include "hb-face.hh"
+#include "hb-shaper.hh"
+
+
+/*
+ * hb_font_funcs_t
+ */
+
+#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
+  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
+  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+  /* ^--- Add new callbacks here */
+
+struct hb_font_funcs_t
+{
+  hb_object_header_t header;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } destroy;
+
+  /* Don't access these directly.  Call font->get_*() instead. */
+  union get_t {
+    struct get_funcs_t {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+    } f;
+    void (*array[0
+#define HB_FONT_FUNC_IMPLEMENT(name) +1
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+               ]) ();
+  } get;
+};
+DECLARE_NULL_INSTANCE (hb_font_funcs_t);
+
+
+/*
+ * hb_font_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_font_t
+{
+  hb_object_header_t header;
+
+  hb_font_t *parent;
+  hb_face_t *face;
+
+  int x_scale;
+  int y_scale;
+
+  unsigned int x_ppem;
+  unsigned int y_ppem;
+
+  float ptem;
+
+  /* Font variation coordinates. */
+  unsigned int num_coords;
+  int *coords;
+
+  hb_font_funcs_t   *klass;
+  void              *user_data;
+  hb_destroy_func_t  destroy;
+
+  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
+
+
+  /* Convert from font-space to user-space */
+  int dir_scale (hb_direction_t direction)
+  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+  hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+  hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+  hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
+  hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
+  float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
+  float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+  { return em_scale (v, dir_scale (direction)); }
+
+  /* Convert from parent-font user-space to our user-space */
+  hb_position_t parent_scale_x_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->x_scale != x_scale))
+      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
+    return v;
+  }
+  hb_position_t parent_scale_y_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->y_scale != y_scale))
+      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
+    return v;
+  }
+  hb_position_t parent_scale_x_position (hb_position_t v)
+  { return parent_scale_x_distance (v); }
+  hb_position_t parent_scale_y_position (hb_position_t v)
+  { return parent_scale_y_distance (v); }
+
+  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_distance (*x);
+    *y = parent_scale_y_distance (*y);
+  }
+  void parent_scale_position (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_position (*x);
+    *y = parent_scale_y_position (*y);
+  }
+
+
+  /* Public getters */
+
+  HB_INTERNAL bool has_func (unsigned int i);
+  HB_INTERNAL bool has_func_set (unsigned int i);
+
+  /* has_* ... */
+#define HB_FONT_FUNC_IMPLEMENT(name) \
+  bool \
+  has_##name##_func () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func (i); \
+  } \
+  bool \
+  has_##name##_func_set () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func_set (i); \
+  }
+  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+
+  hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_h_extents (this, user_data,
+                                       extents,
+                                       klass->user_data.font_h_extents);
+  }
+  hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_v_extents (this, user_data,
+                                       extents,
+                                       klass->user_data.font_v_extents);
+  }
+
+  bool has_glyph (hb_codepoint_t unicode)
+  {
+    hb_codepoint_t glyph;
+    return get_nominal_glyph (unicode, &glyph);
+  }
+
+  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
+                                     hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.nominal_glyph (this, user_data,
+                                      unicode, glyph,
+                                      klass->user_data.nominal_glyph);
+  }
+  unsigned int get_nominal_glyphs (unsigned int count,
+                                  const hb_codepoint_t *first_unicode,
+                                  unsigned int unicode_stride,
+                                  hb_codepoint_t *first_glyph,
+                                  unsigned int glyph_stride)
+  {
+    return klass->get.f.nominal_glyphs (this, user_data,
+                                       count,
+                                       first_unicode, unicode_stride,
+                                       first_glyph, glyph_stride,
+                                       klass->user_data.nominal_glyphs);
+  }
+
+  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+                                hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.variation_glyph (this, user_data,
+                                        unicode, variation_selector, glyph,
+                                        klass->user_data.variation_glyph);
+  }
+
+  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_h_advance (this, user_data,
+                                        glyph,
+                                        klass->user_data.glyph_h_advance);
+  }
+
+  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_v_advance (this, user_data,
+                                        glyph,
+                                        klass->user_data.glyph_v_advance);
+  }
+
+  void get_glyph_h_advances (unsigned int count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned int glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_h_advances (this, user_data,
+                                         count,
+                                         first_glyph, glyph_stride,
+                                         first_advance, advance_stride,
+                                         klass->user_data.glyph_h_advances);
+  }
+
+  void get_glyph_v_advances (unsigned int count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned int glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_v_advances (this, user_data,
+                                         count,
+                                         first_glyph, glyph_stride,
+                                         first_advance, advance_stride,
+                                         klass->user_data.glyph_v_advances);
+  }
+
+  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
+                                      hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_h_origin (this, user_data,
+                                       glyph, x, y,
+                                       klass->user_data.glyph_h_origin);
+  }
+
+  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
+                               hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_v_origin (this, user_data,
+                                       glyph, x, y,
+                                       klass->user_data.glyph_v_origin);
+  }
+
+  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
+                                    hb_codepoint_t right_glyph)
+  {
+    return klass->get.f.glyph_h_kerning (this, user_data,
+                                        left_glyph, right_glyph,
+                                        klass->user_data.glyph_h_kerning);
+  }
+
+  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
+                                    hb_codepoint_t bottom_glyph)
+  {
+    return klass->get.f.glyph_v_kerning (this, user_data,
+                                        top_glyph, bottom_glyph,
+                                        klass->user_data.glyph_v_kerning);
+  }
+
+  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
+                                     hb_glyph_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.glyph_extents (this, user_data,
+                                      glyph,
+                                      extents,
+                                      klass->user_data.glyph_extents);
+  }
+
+  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
+                                           hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_contour_point (this, user_data,
+                                            glyph, point_index,
+                                            x, y,
+                                            klass->user_data.glyph_contour_point);
+  }
+
+  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
+                           char *name, unsigned int size)
+  {
+    if (size) *name = '\0';
+    return klass->get.f.glyph_name (this, user_data,
+                                   glyph,
+                                   name, size,
+                                   klass->user_data.glyph_name);
+  }
+
+  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
+                                hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    if (len == -1) len = strlen (name);
+    return klass->get.f.glyph_from_name (this, user_data,
+                                        name, len,
+                                        glyph,
+                                        klass->user_data.glyph_from_name);
+  }
+
+
+  /* A bit higher-level, and with fallback */
+
+  void get_h_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_h_extents (extents))
+    {
+      extents->ascender = y_scale * .8;
+      extents->descender = extents->ascender - y_scale;
+      extents->line_gap = 0;
+    }
+  }
+  void get_v_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_v_extents (extents))
+    {
+      extents->ascender = x_scale / 2;
+      extents->descender = extents->ascender - x_scale;
+      extents->line_gap = 0;
+    }
+  }
+
+  void get_extents_for_direction (hb_direction_t direction,
+                                 hb_font_extents_t *extents)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_h_extents_with_fallback (extents);
+    else
+      get_v_extents_with_fallback (extents);
+  }
+
+  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      *x = get_glyph_h_advance (glyph);
+    else
+      *y = get_glyph_v_advance (glyph);
+  }
+  void get_glyph_advances_for_direction (hb_direction_t direction,
+                                        unsigned int count,
+                                        const hb_codepoint_t *first_glyph,
+                                        unsigned glyph_stride,
+                                        hb_position_t *first_advance,
+                                        unsigned advance_stride)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+    else
+      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+  }
+
+  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
+                                     hb_position_t *x, hb_position_t *y)
+  {
+    *x = get_glyph_h_advance (glyph) / 2;
+
+    /* TODO cache this somehow?! */
+    hb_font_extents_t extents;
+    get_h_extents_with_fallback (&extents);
+    *y = extents.ascender;
+  }
+
+  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_h_origin (glyph, x, y) &&
+        get_glyph_v_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x -= dx; *y -= dy;
+    }
+  }
+  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_v_origin (glyph, x, y) &&
+        get_glyph_h_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x += dx; *y += dy;
+    }
+  }
+
+  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                      hb_direction_t direction,
+                                      hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_origin_with_fallback (glyph, x, y);
+    else
+      get_glyph_v_origin_with_fallback (glyph, x, y);
+  }
+
+  void add_glyph_h_origin (hb_codepoint_t glyph,
+                          hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_v_origin (hb_codepoint_t glyph,
+                          hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                      hb_direction_t direction,
+                                      hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+
+  void subtract_glyph_h_origin (hb_codepoint_t glyph,
+                               hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_v_origin (hb_codepoint_t glyph,
+                               hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                           hb_direction_t direction,
+                                           hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+
+  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+      *y = 0;
+      *x = get_glyph_h_kerning (first_glyph, second_glyph);
+    } else {
+      *x = 0;
+      *y = get_glyph_v_kerning (first_glyph, second_glyph);
+    }
+  }
+
+  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
+                                         hb_direction_t direction,
+                                         hb_glyph_extents_t *extents)
+  {
+    hb_bool_t ret = get_glyph_extents (glyph, extents);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
+
+    return ret;
+  }
+
+  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
+                                               hb_direction_t direction,
+                                               hb_position_t *x, hb_position_t *y)
+  {
+    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, x, y);
+
+    return ret;
+  }
+
+  /* Generates gidDDD if glyph has no name. */
+  void
+  glyph_to_string (hb_codepoint_t glyph,
+                  char *s, unsigned int size)
+  {
+    if (get_glyph_name (glyph, s, size)) return;
+
+    if (size && snprintf (s, size, "gid%u", glyph) < 0)
+      *s = '\0';
+  }
+
+  /* Parses gidDDD and uniUUUU strings automatically. */
+  hb_bool_t
+  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
+                    hb_codepoint_t *glyph)
+  {
+    if (get_glyph_from_name (s, len, glyph)) return true;
+
+    if (len == -1) len = strlen (s);
+
+    /* Straight glyph index. */
+    if (hb_codepoint_parse (s, len, 10, glyph))
+      return true;
+
+    if (len > 3)
+    {
+      /* gidDDD syntax for glyph indices. */
+      if (0 == strncmp (s, "gid", 3) &&
+         hb_codepoint_parse (s + 3, len - 3, 10, glyph))
+       return true;
+
+      /* uniUUUU and other Unicode character indices. */
+      hb_codepoint_t unichar;
+      if (0 == strncmp (s, "uni", 3) &&
+         hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
+         get_nominal_glyph (unichar, glyph))
+       return true;
+    }
+
+    return false;
+  }
+
+  hb_position_t em_scale (int16_t v, int scale)
+  {
+    int upem = face->get_upem ();
+    int64_t scaled = v * (int64_t) scale;
+    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
+    return (hb_position_t) (scaled / upem);
+  }
+  hb_position_t em_scalef (float v, int scale)
+  { return (hb_position_t) round (v * scale / face->get_upem ()); }
+  float em_fscale (int16_t v, int scale)
+  { return (float) v * scale / face->get_upem (); }
+};
+DECLARE_NULL_INSTANCE (hb_font_t);
+
+
+#endif /* HB_FONT_HH */
index 7caafba..1900f30 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
+#include "hb.hh"
 
 #include "hb-ft.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-cache.hh"
 
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_TRUETYPE_TABLES_H
 
 
+/**
+ * SECTION:hb-ft
+ * @title: hb-ft
+ * @short_description: FreeType integration
+ * @include: hb-ft.h
+ *
+ * Functions for using HarfBuzz with the FreeType library to provide face and
+ * font data.
+ **/
+
+
 /* TODO:
  *
  * In general, this file does a fine job of what it's supposed to do.
  * There are, however, things that need more work:
  *
- *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
- *     Have not investigated.
- *
  *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
  *     would work fine.  However, we also abuse this API for performing in font-space,
  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
  *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
- *     ourselves, like we do in uniscribe, etc.
+ *     ourselves.
  *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
- *
- *   - FT_Load_Glyph() is extremely costly.  Do something about it?
  */
 
 
 struct hb_ft_font_t
 {
+  mutable hb_mutex_t lock;
   FT_Face ft_face;
   int load_flags;
   bool symbol; /* Whether selected cmap is symbol cmap. */
   bool unref; /* Whether to destroy ft_face when done. */
+
+  mutable hb_atomic_int_t cached_x_scale;
+  mutable hb_advance_cache_t advance_cache;
 };
 
 static hb_ft_font_t *
@@ -78,12 +89,16 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
   if (unlikely (!ft_font))
     return nullptr;
 
+  ft_font->lock.init ();
   ft_font->ft_face = ft_face;
   ft_font->symbol = symbol;
   ft_font->unref = unref;
 
   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
+  ft_font->cached_x_scale.set (0);
+  ft_font->advance_cache.init ();
+
   return ft_font;
 }
 
@@ -98,9 +113,13 @@ _hb_ft_font_destroy (void *data)
 {
   hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
 
+  ft_font->advance_cache.fini ();
+
   if (ft_font->unref)
     _hb_ft_face_destroy (ft_font->ft_face);
 
+  ft_font->lock.fini ();
+
   free (ft_font);
 }
 
@@ -116,7 +135,7 @@ _hb_ft_font_destroy (void *data)
 void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
@@ -168,6 +187,7 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
                         void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
 
   if (unlikely (!g))
@@ -191,6 +211,32 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
   return true;
 }
 
+static unsigned int
+hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                         void *font_data,
+                         unsigned int count,
+                         const hb_codepoint_t *first_unicode,
+                         unsigned int unicode_stride,
+                         hb_codepoint_t *first_glyph,
+                         unsigned int glyph_stride,
+                         void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  unsigned int done;
+  for (done = 0;
+       done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
+       done++)
+  {
+    first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+  }
+  /* We don't need to do ft_font->symbol dance here, since HB calls the singular
+   * nominal_glyph() for what we don't handle here. */
+  return done;
+}
+
+
 static hb_bool_t
 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
                           void *font_data,
@@ -200,6 +246,7 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
 
   if (unlikely (!g))
@@ -209,22 +256,45 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_advance (hb_font_t *font,
-                          void *font_data,
-                          hb_codepoint_t glyph,
-                          void *user_data HB_UNUSED)
+static void
+hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                           unsigned count,
+                           const hb_codepoint_t *first_glyph,
+                           unsigned glyph_stride,
+                           hb_position_t *first_advance,
+                           unsigned advance_stride,
+                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Fixed v;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
+  int load_flags = ft_font->load_flags;
+  int mult = font->x_scale < 0 ? -1 : +1;
 
-  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
-    return 0;
+  if (font->x_scale != ft_font->cached_x_scale.get ())
+  {
+    ft_font->advance_cache.clear ();
+    ft_font->cached_x_scale.set (font->x_scale);
+  }
 
-  if (font->x_scale < 0)
-    v = -v;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    FT_Fixed v = 0;
+    hb_codepoint_t glyph = *first_glyph;
 
-  return (v + (1<<9)) >> 10;
+    unsigned int cv;
+    if (ft_font->advance_cache.get (glyph, &cv))
+      v = cv;
+    else
+    {
+      FT_Get_Advance (ft_face, glyph, load_flags, &v);
+      ft_font->advance_cache.set (glyph, v);
+    }
+
+    *first_advance = (v * mult + (1<<9)) >> 10;
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
 static hb_position_t
@@ -234,6 +304,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Fixed v;
 
   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
@@ -256,6 +327,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -274,23 +346,6 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_kerning (hb_font_t *font,
-                          void *font_data,
-                          hb_codepoint_t left_glyph,
-                          hb_codepoint_t right_glyph,
-                          void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Vector kerningv;
-
-  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
-    return 0;
-
-  return kerningv.x;
-}
-
 static hb_bool_t
 hb_ft_get_glyph_extents (hb_font_t *font,
                         void *font_data,
@@ -299,6 +354,7 @@ hb_ft_get_glyph_extents (hb_font_t *font,
                         void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -331,6 +387,7 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
                               void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -356,8 +413,10 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED,
                      void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
 
-  hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
+  hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
   if (ret && (size && !*name))
     ret = false;
 
@@ -372,6 +431,7 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (len < 0)
@@ -404,10 +464,11 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
-  metrics->ascender = ft_face->size->metrics.ascender;
-  metrics->descender = ft_face->size->metrics.descender;
-  metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
+  metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
+  metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
+  metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
   if (font->y_scale < 0)
   {
     metrics->ascender = -metrics->ascender;
@@ -417,41 +478,25 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
   return true;
 }
 
-static hb_font_funcs_t *static_ft_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ft_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ft_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ft_funcs ();
 #endif
 
-static void
-_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
@@ -459,20 +504,35 @@ retry:
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_funcs);
+#endif
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
+    return funcs;
+  }
+} static_ft_funcs;
+
+#if HB_USE_ATEXIT
+static
+void free_static_ft_funcs ()
+{
+  static_ft_funcs.free_instance ();
+}
 #endif
-  };
 
+static hb_font_funcs_t *
+_hb_ft_get_font_funcs ()
+{
+  return static_ft_funcs.get_unconst ();
+}
+
+static void
+_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+{
   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
 
   hb_font_set_funcs (font,
-                    funcs,
+                    _hb_ft_get_font_funcs (),
                     _hb_ft_font_create (ft_face, symbol, unref),
                     _hb_ft_font_destroy);
 }
@@ -498,7 +558,10 @@ reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 
   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
   if (error)
+  {
+    free (buffer);
     return nullptr;
+  }
 
   return hb_blob_create ((const char *) buffer, length,
                         HB_MEMORY_MODE_WRITABLE,
@@ -681,47 +744,47 @@ hb_ft_font_create_referenced (FT_Face ft_face)
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 
+#if HB_USE_ATEXIT
+static void free_static_ft_library ();
+#endif
 
-/* Thread-safe, lock-free, FT_Library */
+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
+                                                            hb_ft_library_lazy_loader_t>
+{
+  static FT_Library create ()
+  {
+    FT_Library l;
+    if (FT_Init_FreeType (&l))
+      return nullptr;
 
-static FT_Library ft_library;
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_library);
+#endif
 
-#ifdef HB_USE_ATEXIT
+    return l;
+  }
+  static void destroy (FT_Library l)
+  {
+    FT_Done_FreeType (l);
+  }
+  static FT_Library get_null ()
+  {
+    return nullptr;
+  }
+} static_ft_library;
+
+#if HB_USE_ATEXIT
 static
-void free_ft_library (void)
+void free_static_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-  if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
-    goto retry;
-
-  FT_Done_FreeType (library);
+  static_ft_library.free_instance ();
 }
 #endif
 
 static FT_Library
-get_ft_library (void)
+get_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-
-  if (unlikely (!library))
-  {
-    /* Not found; allocate one. */
-    if (FT_Init_FreeType (&library))
-      return nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
-      FT_Done_FreeType (library);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_ft_library); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return library;
+  return static_ft_library.get_unconst ();
 }
 
 static void
index 246380a..5763754 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-glib.h"
 
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
+
+
+/**
+ * SECTION:hb-glib
+ * @title: hb-glib
+ * @short_description: GLib integration
+ * @include: hb-glib.h
+ *
+ * Functions for using HarfBuzz with the GLib library to provide Unicode data.
+ **/
 
 
 #if !GLIB_CHECK_VERSION(2,29,14)
@@ -201,14 +211,6 @@ hb_glib_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
   return (hb_unicode_combining_class_t) g_unichar_combining_class (unicode);
 }
 
-static unsigned int
-hb_glib_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                                hb_codepoint_t      unicode,
-                                void               *user_data HB_UNUSED)
-{
-  return g_unichar_iswide (unicode) ? 2 : 1;
-}
-
 static hb_unicode_general_category_t
 hb_glib_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
                                  hb_codepoint_t      unicode,
@@ -333,81 +335,49 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
   return ret;
 }
 
-static unsigned int
-hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                                        hb_codepoint_t      u,
-                                        hb_codepoint_t     *decomposed,
-                                        void               *user_data HB_UNUSED)
-{
-#if GLIB_CHECK_VERSION(2,29,12)
-  return g_unichar_fully_decompose (u, true, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
-#endif
-
-  /* If the user doesn't have GLib >= 2.29.12 we have to perform
-   * a round trip to UTF-8 and the associated memory management dance. */
-  gchar utf8[6];
-  gchar *utf8_decomposed, *c;
-  gsize utf8_len, utf8_decomposed_len, i;
 
-  /* Convert @u to UTF-8 and normalise it in NFKD mode. This performs the compatibility decomposition. */
-  utf8_len = g_unichar_to_utf8 (u, utf8);
-  utf8_decomposed = g_utf8_normalize (utf8, utf8_len, G_NORMALIZE_NFKD);
-  utf8_decomposed_len = g_utf8_strlen (utf8_decomposed, -1);
+#if HB_USE_ATEXIT
+static void free_static_glib_funcs ();
+#endif
 
-  assert (utf8_decomposed_len <= HB_UNICODE_MAX_DECOMPOSITION_LEN);
+static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
+{
+  static hb_unicode_funcs_t *create ()
+  {
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
 
-  for (i = 0, c = utf8_decomposed; i < utf8_decomposed_len; i++, c = g_utf8_next_char (c))
-    *decomposed++ = g_utf8_get_char (c);
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_glib_unicode_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_glib_unicode_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_glib_unicode_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_glib_unicode_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_glib_unicode_compose, nullptr, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_glib_unicode_decompose, nullptr, nullptr);
 
-  g_free (utf8_decomposed);
+    hb_unicode_funcs_make_immutable (funcs);
 
-  return utf8_decomposed_len;
-}
+#if HB_USE_ATEXIT
+    atexit (free_static_glib_funcs);
+#endif
 
-static hb_unicode_funcs_t *static_glib_funcs = nullptr;
+    return funcs;
+  }
+} static_glib_funcs;
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
 static
-void free_static_glib_funcs (void)
+void free_static_glib_funcs ()
 {
-retry:
-  hb_unicode_funcs_t *glib_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, glib_funcs, nullptr))
-    goto retry;
-
-  hb_unicode_funcs_destroy (glib_funcs);
+  static_glib_funcs.free_instance ();
 }
 #endif
 
 hb_unicode_funcs_t *
-hb_glib_get_unicode_funcs (void)
+hb_glib_get_unicode_funcs ()
 {
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
+  return static_glib_funcs.get_unconst ();
+}
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_glib_funcs); /* First person registers atexit() callback. */
-#endif
-  };
 
-  return hb_unicode_funcs_reference (funcs);
-}
 
 #if GLIB_CHECK_VERSION(2,31,10)
 
index ca458a3..e3a9a6b 100644 (file)
@@ -25,7 +25,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 /* g++ didn't like older gtype.h gcc-only code path. */
 #include <glib.h>
@@ -46,7 +46,7 @@
 
 /*** BEGIN value-header ***/
 GType
-@enum_name@_get_type (void)
+@enum_name@_get_type ()
 {
   static gsize type_id = 0;
 
index 606727c..7ef9dfc 100644 (file)
@@ -43,7 +43,7 @@ HB_BEGIN_DECLS
 
 /*** BEGIN value-header ***/
 HB_EXTERN GType
-@enum_name@_get_type (void) G_GNUC_CONST;
+@enum_name@_get_type () G_GNUC_CONST;
 #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
 
 /*** END value-header ***/
index a96c358..3cff880 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+
+/**
+ * SECTION:hb-gobject
+ * @title: hb-gobject
+ * @short_description: GObject integration
+ * @include: hb-gobject.h
+ *
+ * Functions for using HarfBuzz with the GObject library to provide
+ * type data.
+ **/
+
 
 /* g++ didn't like older gtype.h gcc-only code path. */
 #include <glib.h>
@@ -39,7 +51,7 @@
 
 #define HB_DEFINE_BOXED_TYPE(name,copy_func,free_func) \
 GType \
-hb_gobject_##name##_get_type (void) \
+hb_gobject_##name##_get_type () \
 { \
    static gsize type_id = 0; \
    if (g_once_init_enter (&type_id)) { \
@@ -52,7 +64,7 @@ hb_gobject_##name##_get_type (void) \
 }
 
 #define HB_DEFINE_OBJECT_TYPE(name) \
-       HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy);
+       HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy)
 
 #define HB_DEFINE_VALUE_TYPE(name) \
        static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \
@@ -63,7 +75,7 @@ hb_gobject_##name##_get_type (void) \
          return c; \
        } \
        static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \
-       HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy);
+       HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy)
 
 HB_DEFINE_OBJECT_TYPE (buffer)
 HB_DEFINE_OBJECT_TYPE (blob)
@@ -71,6 +83,7 @@ HB_DEFINE_OBJECT_TYPE (face)
 HB_DEFINE_OBJECT_TYPE (font)
 HB_DEFINE_OBJECT_TYPE (font_funcs)
 HB_DEFINE_OBJECT_TYPE (set)
+HB_DEFINE_OBJECT_TYPE (map)
 HB_DEFINE_OBJECT_TYPE (shape_plan)
 HB_DEFINE_OBJECT_TYPE (unicode_funcs)
 HB_DEFINE_VALUE_TYPE (feature)
index 302dc95..800beed 100644 (file)
@@ -90,6 +90,10 @@ hb_gobject_set_get_type (void);
 #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ())
 
 HB_EXTERN GType
+hb_gobject_map_get_type (void);
+#define HB_GOBJECT_TYPE_MAP (hb_gobject_map_get_type ())
+
+HB_EXTERN GType
 hb_gobject_shape_plan_get_type (void);
 #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ())
 
index c20f6be..a1c602c 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER graphite2
-#include "hb-shaper-impl-private.hh"
+#include "hb-shaper-impl.hh"
 
 #include "hb-graphite2.h"
 
 #include <graphite2/Segment.h>
 
+#include "hb-ot-layout.h"
 
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font)
+
+/**
+ * SECTION:hb-graphite2
+ * @title: hb-graphite2
+ * @short_description: Graphite2 integration
+ * @include: hb-graphite2.h
+ *
+ * Functions for using HarfBuzz with the Graphite2 fonts.
+ **/
 
 
 /*
  * shaper face data
  */
 
-typedef struct hb_graphite2_tablelist_t {
+typedef struct hb_graphite2_tablelist_t
+{
   struct hb_graphite2_tablelist_t *next;
   hb_blob_t *blob;
   unsigned int tag;
 } hb_graphite2_tablelist_t;
 
-struct hb_graphite2_shaper_face_data_t {
+struct hb_graphite2_face_data_t
+{
   hb_face_t *face;
   gr_face   *grface;
-  hb_graphite2_tablelist_t *tlist;
+  hb_atomic_ptr_t<hb_graphite2_tablelist_t> tlist;
 };
 
 static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
 {
-  hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
+  hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
   hb_graphite2_tablelist_t *tlist = face_data->tlist;
 
   hb_blob_t *blob = nullptr;
@@ -80,10 +89,10 @@ static const void *hb_graphite2_get_table (const void *data, unsigned int tag, s
     p->tag = tag;
 
 retry:
-    hb_graphite2_tablelist_t *tlist = (hb_graphite2_tablelist_t *) hb_atomic_ptr_get (&face_data->tlist);
+    hb_graphite2_tablelist_t *tlist = face_data->tlist;
     p->next = tlist;
 
-    if (!hb_atomic_ptr_cmpexch (&face_data->tlist, tlist, p))
+    if (unlikely (!face_data->tlist.cmpexch (tlist, p)))
       goto retry;
   }
 
@@ -93,7 +102,33 @@ retry:
   return d;
 }
 
-hb_graphite2_shaper_face_data_t *
+static void hb_graphite2_release_table(const void *data, const void *table_buffer)
+{
+  hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
+  hb_graphite2_tablelist_t *tlist = face_data->tlist;
+
+  hb_graphite2_tablelist_t *prev = nullptr;
+  hb_graphite2_tablelist_t *curr = tlist;
+  while (curr)
+  {
+    if (hb_blob_get_data(curr->blob, nullptr) == table_buffer)
+    {
+      if (prev == nullptr)
+        face_data->tlist.cmpexch(tlist, curr->next);
+      else
+        prev->next = curr->next;
+      hb_blob_destroy(curr->blob);
+      free(curr);
+      break;
+    }
+    prev = curr;
+    curr = curr->next;
+  }
+}
+
+static gr_face_ops hb_graphite2_face_ops = { sizeof(gr_face_ops), hb_graphite2_get_table, hb_graphite2_release_table };
+
+hb_graphite2_face_data_t *
 _hb_graphite2_shaper_face_data_create (hb_face_t *face)
 {
   hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
@@ -106,12 +141,12 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
   }
   hb_blob_destroy (silf_blob);
 
-  hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
+  hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t));
   if (unlikely (!data))
     return nullptr;
 
   data->face = face;
-  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
+  data->grface = gr_make_face_with_ops (data, &hb_graphite2_face_ops, gr_face_preloadAll);
 
   if (unlikely (!data->grface)) {
     free (data);
@@ -122,7 +157,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
 }
 
 void
-_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
+_hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
 {
   hb_graphite2_tablelist_t *tlist = data->tlist;
 
@@ -145,8 +180,8 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
 gr_face *
 hb_graphite2_face_get_gr_face (hb_face_t *face)
 {
-  if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return nullptr;
-  return HB_SHAPER_DATA_GET (face)->grface;
+  const hb_graphite2_face_data_t *data = face->data.graphite2;
+  return data ? data->grface : nullptr;
 }
 
 
@@ -154,52 +189,33 @@ hb_graphite2_face_get_gr_face (hb_face_t *face)
  * shaper font data
  */
 
-struct hb_graphite2_shaper_font_data_t {};
+struct hb_graphite2_font_data_t {};
 
-hb_graphite2_shaper_font_data_t *
+hb_graphite2_font_data_t *
 _hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_graphite2_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED)
+_hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED)
 {
 }
 
-/*
+/**
+ * hb_graphite2_font_get_gr_font:
+ *
  * Since: 0.9.10
+ * Deprecated: 1.4.2
  */
 gr_font *
-hb_graphite2_font_get_gr_font (hb_font_t *font)
+hb_graphite2_font_get_gr_font (hb_font_t *font HB_UNUSED)
 {
   return nullptr;
 }
 
 
 /*
- * shaper shape_plan data
- */
-
-struct hb_graphite2_shaper_shape_plan_data_t {};
-
-hb_graphite2_shaper_shape_plan_data_t *
-_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
  * shaper
  */
 
@@ -213,14 +229,14 @@ struct hb_graphite2_cluster_t {
 };
 
 hb_bool_t
-_hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
+_hb_graphite2_shape (hb_shape_plan_t    *shape_plan HB_UNUSED,
                     hb_font_t          *font,
                     hb_buffer_t        *buffer,
                     const hb_feature_t *features,
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
+  gr_face *grface = face->data.graphite2->grface;
 
   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   const char *lang_end = lang ? strchr (lang, '-') : nullptr;
@@ -249,11 +265,16 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
 
   /* TODO ensure_native_direction. */
 
-  hb_tag_t script_tag[2];
-  hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
+  hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT];
+  unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT;
+  hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer),
+                                      HB_LANGUAGE_INVALID,
+                                      &count,
+                                      script_tag,
+                                      nullptr, nullptr);
 
   seg = gr_make_seg (nullptr, grface,
-                    script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
+                    count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT,
                     feats,
                     gr_utf32, chars, buffer->len,
                     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
index 05c55de..1720191 100644 (file)
@@ -41,7 +41,7 @@ hb_graphite2_face_get_gr_face (hb_face_t *face);
 
 #ifndef HB_DISABLE_DEPRECATED
 
-HB_EXTERN gr_font *
+HB_EXTERN HB_DEPRECATED_FOR (hb_graphite2_face_get_gr_face) gr_font *
 hb_graphite2_font_get_gr_font (hb_font_t *font);
 
 #endif
index c52e165..c26c91d 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-icu.h"
 
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
 
 #include <unicode/uchar.h>
 #include <unicode/unorm2.h>
 #include <unicode/uversion.h>
 
 
+/**
+ * SECTION:hb-icu
+ * @title: hb-icu
+ * @short_description: ICU integration
+ * @include: hb-icu.h
+ *
+ * Functions for using HarfBuzz with the ICU library to provide Unicode data.
+ **/
+
+
 hb_script_t
 hb_icu_script_to_script (UScriptCode script)
 {
@@ -55,7 +65,8 @@ hb_icu_script_from_script (hb_script_t script)
   if (unlikely (script == HB_SCRIPT_INVALID))
     return USCRIPT_INVALID_CODE;
 
-  for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
+  unsigned int numScriptCode = 1 + u_getIntPropertyMaxValue (UCHAR_SCRIPT);
+  for (unsigned int i = 0; i < numScriptCode; i++)
     if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script))
       return (UScriptCode) i;
 
@@ -72,25 +83,6 @@ hb_icu_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
   return (hb_unicode_combining_class_t) u_getCombiningClass (unicode);
 }
 
-static unsigned int
-hb_icu_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                               hb_codepoint_t      unicode,
-                               void               *user_data HB_UNUSED)
-{
-  switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH))
-  {
-  case U_EA_WIDE:
-  case U_EA_FULLWIDTH:
-    return 2;
-  case U_EA_NEUTRAL:
-  case U_EA_AMBIGUOUS:
-  case U_EA_HALFWIDTH:
-  case U_EA_NARROW:
-    return 1;
-  }
-  return 1;
-}
-
 static hb_unicode_general_category_t
 hb_icu_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
                                 hb_codepoint_t      unicode,
@@ -164,10 +156,6 @@ hb_icu_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
   return hb_icu_script_to_script (scriptCode);
 }
 
-#if U_ICU_VERSION_MAJOR_NUM >= 49
-static const UNormalizer2 *normalizer;
-#endif
-
 static hb_bool_t
 hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
                        hb_codepoint_t      a,
@@ -177,6 +165,7 @@ hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 {
 #if U_ICU_VERSION_MAJOR_NUM >= 49
   {
+    const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
     UChar32 ret = unorm2_composePair (normalizer, a, b);
     if (ret < 0) return false;
     *ab = ret;
@@ -222,6 +211,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
 {
 #if U_ICU_VERSION_MAJOR_NUM >= 49
   {
+    const UNormalizer2 *normalizer = (const UNormalizer2 *) user_data;
     UChar decomposed[4];
     int len;
     UErrorCode icu_err = U_ZERO_ERROR;
@@ -310,90 +300,51 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
   return ret;
 }
 
-static unsigned int
-hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                                       hb_codepoint_t      u,
-                                       hb_codepoint_t     *decomposed,
-                                       void               *user_data HB_UNUSED)
-{
-  UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
-  unsigned int len;
-  int32_t utf32_len;
-  hb_bool_t err;
-  UErrorCode icu_err;
-
-  /* Copy @u into a UTF-16 array to be passed to ICU. */
-  len = 0;
-  err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
-  if (err)
-    return 0;
-
-  /* Normalise the codepoint using NFKD mode. */
-  icu_err = U_ZERO_ERROR;
-  len = unorm2_normalize (unorm2_getNFKDInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-  if (U_FAILURE (icu_err))
-    return 0;
 
-  /* Convert the decomposed form from UTF-16 to UTF-32. */
-  icu_err = U_ZERO_ERROR;
-  u_strToUTF32 ((UChar32*) decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN, &utf32_len, normalized, len, &icu_err);
-  if (U_FAILURE (icu_err))
-    return 0;
-
-  return utf32_len;
-}
-
-
-static hb_unicode_funcs_t *static_icu_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_icu_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *icu_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, icu_funcs, nullptr))
-    goto retry;
-
-  hb_unicode_funcs_destroy (icu_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_icu_funcs ();
 #endif
 
-hb_unicode_funcs_t *
-hb_icu_get_unicode_funcs (void)
+static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
 {
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
-
-  if (unlikely (!funcs))
+  static hb_unicode_funcs_t *create ()
   {
+    void *user_data = nullptr;
 #if U_ICU_VERSION_MAJOR_NUM >= 49
-    if (!hb_atomic_ptr_get (&normalizer)) {
-      UErrorCode icu_err = U_ZERO_ERROR;
-      /* We ignore failure in getNFCInstace(). */
-      (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
-    }
+    UErrorCode icu_err = U_ZERO_ERROR;
+    user_data = (void *) unorm2_getNFCInstance (&icu_err);
+    assert (user_data);
 #endif
 
-    funcs = hb_unicode_funcs_create (nullptr);
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
 
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_icu_unicode_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_icu_unicode_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_icu_unicode_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_icu_unicode_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_icu_unicode_compose, user_data, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_icu_unicode_decompose, user_data, nullptr);
 
     hb_unicode_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_icu_funcs);
+#endif
+
+    return funcs;
+  }
+} static_icu_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_icu_funcs ()
+{
+  static_icu_funcs.free_instance ();
+}
 #endif
-  };
 
-  return hb_unicode_funcs_reference (funcs);
+hb_unicode_funcs_t *
+hb_icu_get_unicode_funcs ()
+{
+  return static_icu_funcs.get_unconst ();
 }
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
new file mode 100644 (file)
index 0000000..c4ab26d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ITER_HH
+#define HB_ITER_HH
+
+#include "hb.hh"
+#include "hb-null.hh"
+
+
+/* Unified iterator object.
+ *
+ * The goal of this template is to make the same iterator interface
+ * available to all types, and make it very easy and compact to use.
+ * hb_iter_tator objects are small, light-weight, objects that can be
+ * copied by value.  If the collection / object being iterated on
+ * is writable, then the iterator returns lvalues, otherwise it
+ * returns rvalues.
+ */
+
+/* Base class for all iterators. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_iter_t
+{
+  typedef Iter iter_t;
+  typedef iter_t const_iter_t;
+  typedef Item item_t;
+  static constexpr unsigned item_size = hb_static_size (Item);
+
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Operators. */
+  operator iter_t () { return iter(); }
+  explicit_operator bool () const { return more (); }
+  item_t& operator * () const { return item (); }
+  item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
+  iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
+  iter_t& operator ++ () { next (); return *thiz(); }
+  iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
+  iter_t& operator -- () { prev (); return *thiz(); }
+  iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
+  iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
+  iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
+  iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
+
+  /* Methods. */
+  iter_t iter () const { return *thiz(); }
+  const_iter_t const_iter () const { return iter (); }
+  item_t& item () const { return thiz()->__item__ (); }
+  item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
+  bool more () const { return thiz()->__more__ (); }
+  unsigned len () const { return thiz()->__len__ (); }
+  void next () { thiz()->__next__ (); }
+  void forward (unsigned n) { thiz()->__forward__ (n); }
+  void prev () { thiz()->__prev__ (); }
+  void rewind (unsigned n) { thiz()->__rewind__ (n); }
+  bool random_access () const { return thiz()->__random_access__ (); }
+
+  protected:
+  hb_iter_t () {}
+  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
+  void operator = (const hb_iter_t &o HB_UNUSED) {}
+};
+
+/* Base class for sorted iterators.  Does not enforce anything.
+ * Just for class taxonomy and requirements. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_sorted_iter_t : hb_iter_t<Iter, Item>
+{
+  protected:
+  hb_sorted_iter_t () {}
+  hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t<Iter, Item> (o) {}
+  void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
+};
+
+/* Mixin to fill in what the subclass doesn't provide. */
+template <typename iter_t, typename item_t = typename iter_t::__item_type__>
+struct hb_iter_mixin_t
+{
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Access: Implement __item__(), or __item_at__() if random-access. */
+  item_t& __item__ () const { return thiz()->item_at (0); }
+  item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
+
+  /* Termination: Implement __more__(), or __len__() if random-access. */
+  bool __more__ () const { return thiz()->__len__ (); }
+  unsigned __len__ () const
+  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
+
+  /* Advancing: Implement __next__(), or __forward__() if random-access. */
+  void __next__ () { thiz()->forward (1); }
+  void __forward__ (unsigned n) { while (n--) thiz()->next (); }
+
+  /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
+  void __prev__ () { thiz()->rewind (1); }
+  void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
+
+  /* Random access: Return true if item_at(), len(), forward() are fast. */
+  bool __random_access__ () const { return false; }
+};
+
+
+/* Functions operating on iterators or iteratables. */
+
+template <typename C, typename V> inline void
+hb_fill (const C& c, const V &v)
+{
+  for (typename C::iter_t i (c); i; i++)
+    hb_assign (*i, v);
+}
+
+template <typename S, typename D> inline bool
+hb_copy (hb_iter_t<D> &id, hb_iter_t<S> &is)
+{
+  for (; id && is; ++id, ++is)
+    *id = *is;
+  return !is;
+}
+
+
+#endif /* HB_ITER_HH */
diff --git a/src/hb-kern.hh b/src/hb-kern.hh
new file mode 100644 (file)
index 0000000..fd5bb9e
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_KERN_HH
+#define HB_KERN_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+namespace OT {
+
+
+template <typename Driver>
+struct hb_kern_machine_t
+{
+  hb_kern_machine_t (const Driver &driver_,
+                    bool crossStream_ = false) :
+                      driver (driver_),
+                      crossStream (crossStream_) {}
+
+  HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+  void kern (hb_font_t   *font,
+            hb_buffer_t *buffer,
+            hb_mask_t    kern_mask,
+            bool         scale = true) const
+  {
+    OT::hb_ot_apply_context_t c (1, font, buffer);
+    c.set_lookup_mask (kern_mask);
+    c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
+    OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+    skippy_iter.init (&c);
+
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
+    unsigned int count = buffer->len;
+    hb_glyph_info_t *info = buffer->info;
+    hb_glyph_position_t *pos = buffer->pos;
+    for (unsigned int idx = 0; idx < count;)
+    {
+      if (!(info[idx].mask & kern_mask))
+      {
+       idx++;
+       continue;
+      }
+
+      skippy_iter.reset (idx, 1);
+      if (!skippy_iter.next ())
+      {
+       idx++;
+       continue;
+      }
+
+      unsigned int i = idx;
+      unsigned int j = skippy_iter.idx;
+
+      hb_position_t kern = driver.get_kerning (info[i].codepoint,
+                                              info[j].codepoint);
+
+
+      if (likely (!kern))
+        goto skip;
+
+      if (horizontal)
+      {
+        if (scale)
+         kern = font->em_scale_x (kern);
+       if (crossStream)
+       {
+         pos[j].y_offset = kern;
+         buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+       }
+       else
+       {
+         hb_position_t kern1 = kern >> 1;
+         hb_position_t kern2 = kern - kern1;
+         pos[i].x_advance += kern1;
+         pos[j].x_advance += kern2;
+         pos[j].x_offset += kern2;
+       }
+      }
+      else
+      {
+        if (scale)
+         kern = font->em_scale_y (kern);
+       if (crossStream)
+       {
+         pos[j].x_offset = kern;
+         buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+       }
+       else
+       {
+         hb_position_t kern1 = kern >> 1;
+         hb_position_t kern2 = kern - kern1;
+         pos[i].y_advance += kern1;
+         pos[j].y_advance += kern2;
+         pos[j].y_offset += kern2;
+       }
+      }
+
+      buffer->unsafe_to_break (i, j + 1);
+
+    skip:
+      idx = skippy_iter.idx;
+    }
+  }
+
+  const Driver &driver;
+  bool crossStream;
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_KERN_HH */
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
new file mode 100644 (file)
index 0000000..b22c238
--- /dev/null
@@ -0,0 +1,931 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2012,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MACHINERY_HH
+#define HB_MACHINERY_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+
+#include "hb-array.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Casts
+ */
+
+/* Cast to struct T, reference to reference */
+template<typename Type, typename TObject>
+static inline const Type& CastR(const TObject &X)
+{ return reinterpret_cast<const Type&> (X); }
+template<typename Type, typename TObject>
+static inline Type& CastR(TObject &X)
+{ return reinterpret_cast<Type&> (X); }
+
+/* Cast to struct T, pointer to pointer */
+template<typename Type, typename TObject>
+static inline const Type* CastP(const TObject *X)
+{ return reinterpret_cast<const Type*> (X); }
+template<typename Type, typename TObject>
+static inline Type* CastP(TObject *X)
+{ return reinterpret_cast<Type*> (X); }
+
+/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
+ * location pointed to by P plus Ofs bytes. */
+template<typename Type>
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
+{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
+template<typename Type>
+static inline Type& StructAtOffset(void *P, unsigned int offset)
+{ return * reinterpret_cast<Type*> ((char *) P + offset); }
+template<typename Type>
+static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+template<typename Type>
+static inline Type& StructAtOffsetUnaligned(void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+
+/* StructAfter<T>(X) returns the struct T& that is placed after X.
+ * Works with X of variable size also.  X must implement get_size() */
+template<typename Type, typename TObject>
+static inline const Type& StructAfter(const TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+template<typename Type, typename TObject>
+static inline Type& StructAfter(TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+
+
+/*
+ * Size checking
+ */
+
+/* Check _assertion in a method environment */
+#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
+  void _instance_assertion_on_line_##_line () const \
+  { static_assert ((_assertion), ""); }
+# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
+# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
+
+/* Check that _code compiles in a method environment */
+#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
+  void _compiles_assertion_on_line_##_line () const \
+  { _code; }
+# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
+# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
+
+
+#define DEFINE_SIZE_STATIC(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)) \
+  unsigned int get_size () const { return (size); } \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size); \
+  static constexpr unsigned static_size = (size)
+
+#define DEFINE_SIZE_UNION(size, _member) \
+  DEFINE_COMPILES_ASSERTION ((void) this->u._member.static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof(this->u._member) == (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_MIN(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_UNBOUNDED(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY(size, array) \
+  DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
+  unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \
+  DEFINE_SIZE_ARRAY(size, array)
+
+
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+  static constexpr unsigned max_debug_depth = MaxDebugDepth;
+  typedef Return return_t;
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
+  static return_t no_dispatch_return_value () { return Context::default_return_value (); }
+  static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
+};
+
+
+/*
+ * Sanitize
+ *
+ *
+ * === Introduction ===
+ *
+ * The sanitize machinery is at the core of our zero-cost font loading.  We
+ * mmap() font file into memory and create a blob out of it.  Font subtables
+ * are returned as a readonly sub-blob of the main font blob.  These table
+ * blobs are then sanitized before use, to ensure invalid memory access does
+ * not happen.  The toplevel sanitize API use is like, eg. to load the 'head'
+ * table:
+ *
+ *   hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (face);
+ *
+ * The blob then can be converted to a head table struct with:
+ *
+ *   const head *head_table = head_blob->as<head> ();
+ *
+ * What the reference_table does is, to call hb_face_reference_table() to load
+ * the table blob, sanitize it and return either the sanitized blob, or empty
+ * blob if sanitization failed.  The blob->as() function returns the null
+ * object of its template type argument if the blob is empty.  Otherwise, it
+ * just casts the blob contents to the desired type.
+ *
+ * Sanitizing a blob of data with a type T works as follows (with minor
+ * simplification):
+ *
+ *   - Cast blob content to T*, call sanitize() method of it,
+ *   - If sanitize succeeded, return blob.
+ *   - Otherwise, if blob is not writable, try making it writable,
+ *     or copy if cannot be made writable in-place,
+ *   - Call sanitize() again.  Return blob if sanitize succeeded.
+ *   - Return empty blob otherwise.
+ *
+ *
+ * === The sanitize() contract ===
+ *
+ * The sanitize() method of each object type shall return true if it's safe to
+ * call other methods of the object, and false otherwise.
+ *
+ * Note that what sanitize() checks for might align with what the specification
+ * describes as valid table data, but does not have to be.  In particular, we
+ * do NOT want to be pedantic and concern ourselves with validity checks that
+ * are irrelevant to our use of the table.  On the contrary, we want to be
+ * lenient with error handling and accept invalid data to the extent that it
+ * does not impose extra burden on us.
+ *
+ * Based on the sanitize contract, one can see that what we check for depends
+ * on how we use the data in other table methods.  Ie. if other table methods
+ * assume that offsets do NOT point out of the table data block, then that's
+ * something sanitize() must check for (GSUB/GPOS/GDEF/etc work this way).  On
+ * the other hand, if other methods do such checks themselves, then sanitize()
+ * does not have to bother with them (glyf/local work this way).  The choice
+ * depends on the table structure and sanitize() performance.  For example, to
+ * check glyf/loca offsets in sanitize() would cost O(num-glyphs).  We try hard
+ * to avoid such costs during font loading.  By postponing such checks to the
+ * actual glyph loading, we reduce the sanitize cost to O(1) and total runtime
+ * cost to O(used-glyphs).  As such, this is preferred.
+ *
+ * The same argument can be made re GSUB/GPOS/GDEF, but there, the table
+ * structure is so complicated that by checking all offsets at sanitize() time,
+ * we make the code much simpler in other methods, as offsets and referenced
+ * objects do not need to be validated at each use site.
+ */
+
+/* This limits sanitizing time on really broken fonts. */
+#ifndef HB_SANITIZE_MAX_EDITS
+#define HB_SANITIZE_MAX_EDITS 32
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_FACTOR
+#define HB_SANITIZE_MAX_OPS_FACTOR 8
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MIN
+#define HB_SANITIZE_MAX_OPS_MIN 16384
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MAX
+#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
+#endif
+
+struct hb_sanitize_context_t :
+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
+{
+  hb_sanitize_context_t () :
+       debug_depth (0),
+       start (nullptr), end (nullptr),
+       max_ops (0),
+       writable (false), edit_count (0),
+       blob (nullptr),
+       num_glyphs (65536),
+       num_glyphs_set (false) {}
+
+  const char *get_name () { return "SANITIZE"; }
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format)
+  { return format->sanitize (this); }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.sanitize (this); }
+  static return_t default_return_value () { return true; }
+  static return_t no_dispatch_return_value () { return false; }
+  bool stop_sublookup_iteration (const return_t r) const { return !r; }
+
+  void init (hb_blob_t *b)
+  {
+    this->blob = hb_blob_reference (b);
+    this->writable = false;
+  }
+
+  void set_num_glyphs (unsigned int num_glyphs_)
+  {
+    num_glyphs = num_glyphs_;
+    num_glyphs_set = true;
+  }
+  unsigned int get_num_glyphs () { return num_glyphs; }
+
+  void set_max_ops (int max_ops_) { max_ops = max_ops_; }
+
+  template <typename T>
+  void set_object (const T *obj)
+  {
+    reset_object ();
+
+    if (!obj) return;
+
+    const char *obj_start = (const char *) obj;
+    if (unlikely (obj_start < this->start || this->end <= obj_start))
+      this->start = this->end = nullptr;
+    else
+    {
+      this->start = obj_start;
+      this->end   = obj_start + MIN<uintptr_t> (this->end - obj_start, obj->get_size ());
+    }
+  }
+
+  void reset_object ()
+  {
+    this->start = this->blob->data;
+    this->end = this->start + this->blob->length;
+    assert (this->start <= this->end); /* Must not overflow. */
+  }
+
+  void start_processing ()
+  {
+    reset_object ();
+    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+                        (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+    this->edit_count = 0;
+    this->debug_depth = 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
+                    "start [%p..%p] (%lu bytes)",
+                    this->start, this->end,
+                    (unsigned long) (this->end - this->start));
+  }
+
+  void end_processing ()
+  {
+    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
+                    "end [%p..%p] %u edit requests",
+                    this->start, this->end, this->edit_count);
+
+    hb_blob_destroy (this->blob);
+    this->blob = nullptr;
+    this->start = this->end = nullptr;
+  }
+
+  bool check_range (const void *base,
+                          unsigned int len) const
+  {
+    const char *p = (const char *) base;
+    bool ok = this->start <= p &&
+             p <= this->end &&
+             (unsigned int) (this->end - p) >= len &&
+             this->max_ops-- > 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       p, p + len, len,
+       this->start, this->end,
+       ok ? "OK" : "OUT-OF-RANGE");
+
+    return likely (ok);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                          unsigned int a,
+                          unsigned int b) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+          this->check_range (base, a * b);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                          unsigned int a,
+                          unsigned int b,
+                          unsigned int c) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+          this->check_range (base, a * b, c);
+  }
+
+  template <typename T>
+  bool check_array (const T *base, unsigned int len) const
+  {
+    return this->check_range (base, len, hb_static_size (T));
+  }
+
+  template <typename T>
+  bool check_array (const T *base,
+                   unsigned int a,
+                   unsigned int b) const
+  {
+    return this->check_range (base, a, b, hb_static_size (T));
+  }
+
+  template <typename Type>
+  bool check_struct (const Type *obj) const
+  { return likely (this->check_range (obj, obj->min_size)); }
+
+  bool may_edit (const void *base, unsigned int len)
+  {
+    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
+      return false;
+
+    const char *p = (const char *) base;
+    this->edit_count++;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       this->edit_count,
+       p, p + len, len,
+       this->start, this->end,
+       this->writable ? "GRANTED" : "DENIED");
+
+    return this->writable;
+  }
+
+  template <typename Type, typename ValueType>
+  bool try_set (const Type *obj, const ValueType &v)
+  {
+    if (this->may_edit (obj, hb_static_size (Type)))
+    {
+      hb_assign (* const_cast<Type *> (obj), v);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename Type>
+  hb_blob_t *sanitize_blob (hb_blob_t *blob)
+  {
+    bool sane;
+
+    init (blob);
+
+  retry:
+    DEBUG_MSG_FUNC (SANITIZE, start, "start");
+
+    start_processing ();
+
+    if (unlikely (!start))
+    {
+      end_processing ();
+      return blob;
+    }
+
+    Type *t = CastP<Type> (const_cast<char *> (start));
+
+    sane = t->sanitize (this);
+    if (sane)
+    {
+      if (edit_count)
+      {
+       DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
+
+        /* sanitize again to ensure no toe-stepping */
+        edit_count = 0;
+       sane = t->sanitize (this);
+       if (edit_count) {
+         DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
+         sane = false;
+       }
+      }
+    }
+    else
+    {
+      if (edit_count && !writable) {
+        start = hb_blob_get_data_writable (blob, nullptr);
+       end = start + blob->length;
+
+       if (start)
+       {
+         writable = true;
+         /* ok, we made it writable by relocating.  try again */
+         DEBUG_MSG_FUNC (SANITIZE, start, "retry");
+         goto retry;
+       }
+      }
+    }
+
+    end_processing ();
+
+    DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
+    if (sane)
+    {
+      hb_blob_make_immutable (blob);
+      return blob;
+    }
+    else
+    {
+      hb_blob_destroy (blob);
+      return hb_blob_get_empty ();
+    }
+  }
+
+  template <typename Type>
+  hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
+  {
+    if (!num_glyphs_set)
+      set_num_glyphs (hb_face_get_glyph_count (face));
+    return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
+  }
+
+  mutable unsigned int debug_depth;
+  const char *start, *end;
+  mutable int max_ops;
+  private:
+  bool writable;
+  unsigned int edit_count;
+  hb_blob_t *blob;
+  unsigned int num_glyphs;
+  bool  num_glyphs_set;
+};
+
+struct hb_sanitize_with_object_t
+{
+  template <typename T>
+  hb_sanitize_with_object_t (hb_sanitize_context_t *c,
+                                   const T& obj) : c (c)
+  { c->set_object (obj); }
+  ~hb_sanitize_with_object_t ()
+  { c->reset_object (); }
+
+  private:
+  hb_sanitize_context_t *c;
+};
+
+
+/*
+ * Serialize
+ */
+
+struct hb_serialize_context_t
+{
+  hb_serialize_context_t (void *start_, unsigned int size)
+  {
+    this->start = (char *) start_;
+    this->end = this->start + size;
+    reset ();
+  }
+
+  bool in_error () const { return !this->successful; }
+
+  void reset ()
+  {
+    this->successful = true;
+    this->head = this->start;
+    this->debug_depth = 0;
+  }
+
+  bool propagate_error (bool e)
+  { return this->successful = this->successful && e; }
+  template <typename T> bool propagate_error (const T &obj)
+  { return this->successful = this->successful && !obj.in_error (); }
+  template <typename T> bool propagate_error (const T *obj)
+  { return this->successful = this->successful && !obj->in_error (); }
+  template <typename T1, typename T2> bool propagate_error (T1 &o1, T2 &o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2> bool propagate_error (T1 *o1, T2 *o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 &o1, T2 &o2, T3 &o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 *o1, T2 *o2, T3 *o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+
+  /* To be called around main operation. */
+  template <typename Type>
+  Type *start_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
+                    "start [%p..%p] (%lu bytes)",
+                    this->start, this->end,
+                    (unsigned long) (this->end - this->start));
+
+    return start_embed<Type> ();
+  }
+  void end_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
+                    "end [%p..%p] serialized %d bytes; %s",
+                    this->start, this->end,
+                    (int) (this->head - this->start),
+                    this->successful ? "successful" : "UNSUCCESSFUL");
+  }
+
+  unsigned int length () const { return this->head - this->start; }
+
+  void align (unsigned int alignment)
+  {
+    unsigned int l = length () % alignment;
+    if (l)
+      allocate_size<void> (alignment - l);
+  }
+
+  template <typename Type>
+  Type *start_embed (const Type *_ HB_UNUSED = nullptr) const
+  {
+    Type *ret = reinterpret_cast<Type *> (this->head);
+    return ret;
+  }
+
+  template <typename Type>
+  Type *allocate_size (unsigned int size)
+  {
+    if (unlikely (!this->successful || this->end - this->head < ptrdiff_t (size))) {
+      this->successful = false;
+      return nullptr;
+    }
+    memset (this->head, 0, size);
+    char *ret = this->head;
+    this->head += size;
+    return reinterpret_cast<Type *> (ret);
+  }
+
+  template <typename Type>
+  Type *allocate_min ()
+  {
+    return this->allocate_size<Type> (Type::min_size);
+  }
+
+  template <typename Type>
+  Type *embed (const Type &obj)
+  {
+    unsigned int size = obj.get_size ();
+    Type *ret = this->allocate_size<Type> (size);
+    if (unlikely (!ret)) return nullptr;
+    memcpy (ret, &obj, size);
+    return ret;
+  }
+  template <typename Type>
+  hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
+
+  template <typename Type>
+  Type *extend_size (Type &obj, unsigned int size)
+  {
+    assert (this->start <= (char *) &obj);
+    assert ((char *) &obj <= this->head);
+    assert ((char *) &obj + size >= this->head);
+    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
+    return reinterpret_cast<Type *> (&obj);
+  }
+
+  template <typename Type>
+  Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); }
+
+  template <typename Type>
+  Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); }
+
+  /* Output routines. */
+  template <typename Type>
+  Type *copy () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    return reinterpret_cast<Type *> (p);
+  }
+  hb_bytes_t copy_bytes () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    else
+      return hb_bytes_t ();
+    return hb_bytes_t ((char *) p, len);
+  }
+  hb_blob_t *copy_blob () const
+  {
+    assert (this->successful);
+    return hb_blob_create (this->start,
+                          this->head - this->start,
+                          HB_MEMORY_MODE_DUPLICATE,
+                          nullptr, nullptr);
+  }
+
+  public:
+  unsigned int debug_depth;
+  char *start, *end, *head;
+  bool successful;
+};
+
+
+
+/*
+ * Big-endian integers.
+ */
+
+template <typename Type, int Bytes> struct BEInt;
+
+template <typename Type>
+struct BEInt<Type, 1>
+{
+  public:
+  void set (Type V)      { v = V; }
+  operator Type () const { return v; }
+  private: uint8_t v;
+};
+template <typename Type>
+struct BEInt<Type, 2>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >>  8) & 0xFF;
+    v[1] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+    defined(__BYTE_ORDER) && \
+    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+    /* Spoon-feed the compiler a big-endian integer with alignment 1.
+     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+    struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+    return ((packed_uint16_t *) this)->v;
+#endif
+#endif
+    return (v[0] <<  8)
+         + (v[1]      );
+  }
+  private: uint8_t v[2];
+};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >> 16) & 0xFF;
+    v[1] = (V >>  8) & 0xFF;
+    v[2] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 16)
+         + (v[1] <<  8)
+         + (v[2]      );
+  }
+  private: uint8_t v[3];
+};
+template <typename Type>
+struct BEInt<Type, 4>
+{
+  public:
+  typedef Type type;
+  void set (Type V)
+  {
+    v[0] = (V >> 24) & 0xFF;
+    v[1] = (V >> 16) & 0xFF;
+    v[2] = (V >>  8) & 0xFF;
+    v[3] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 24)
+         + (v[1] << 16)
+         + (v[2] <<  8)
+         + (v[3]      );
+  }
+  private: uint8_t v[4];
+};
+
+
+/*
+ * Lazy loaders.
+ */
+
+template <typename Data, unsigned int WheresData>
+struct hb_data_wrapper_t
+{
+  static_assert (WheresData > 0, "");
+
+  Data * get_data () const
+  { return *(((Data **) (void *) this) - WheresData); }
+
+  bool is_inert () const { return !get_data (); }
+
+  template <typename Stored, typename Subclass>
+  Stored * call_create () const { return Subclass::create (get_data ()); }
+};
+template <>
+struct hb_data_wrapper_t<void, 0>
+{
+  bool is_inert () const { return false; }
+
+  template <typename Stored, typename Funcs>
+  Stored * call_create () const { return Funcs::create (); }
+};
+
+template <typename T1, typename T2> struct hb_non_void_t { typedef T1 value; };
+template <typename T2> struct hb_non_void_t<void, T2> { typedef T2 value; };
+
+template <typename Returned,
+         typename Subclass = void,
+         typename Data = void,
+         unsigned int WheresData = 0,
+         typename Stored = Returned>
+struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
+{
+  typedef typename hb_non_void_t<Subclass,
+                                hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
+                               >::value Funcs;
+
+  void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
+  void init ()  { instance.set_relaxed (nullptr); }
+  void fini ()  { do_destroy (instance.get ()); }
+
+  void free_instance ()
+  {
+  retry:
+    Stored *p = instance.get ();
+    if (unlikely (p && !cmpexch (p, nullptr)))
+      goto retry;
+    do_destroy (p);
+  }
+
+  static void do_destroy (Stored *p)
+  {
+    if (p && p != const_cast<Stored *> (Funcs::get_null ()))
+      Funcs::destroy (p);
+  }
+
+  const Returned * operator -> () const { return get (); }
+  const Returned & operator * () const  { return *get (); }
+  explicit_operator bool () const
+  { return get_stored () != Funcs::get_null (); }
+  template <typename C> operator const C * () const { return get (); }
+
+  Stored * get_stored () const
+  {
+  retry:
+    Stored *p = this->instance.get ();
+    if (unlikely (!p))
+    {
+      if (unlikely (this->is_inert ()))
+       return const_cast<Stored *> (Funcs::get_null ());
+
+      p = this->template call_create<Stored, Funcs> ();
+      if (unlikely (!p))
+       p = const_cast<Stored *> (Funcs::get_null ());
+
+      if (unlikely (!cmpexch (nullptr, p)))
+      {
+        do_destroy (p);
+       goto retry;
+      }
+    }
+    return p;
+  }
+  Stored * get_stored_relaxed () const
+  {
+    return this->instance.get_relaxed ();
+  }
+
+  bool cmpexch (Stored *current, Stored *value) const
+  {
+    /* This *must* be called when there are no other threads accessing. */
+    return this->instance.cmpexch (current, value);
+  }
+
+  const Returned * get () const { return Funcs::convert (get_stored ()); }
+  const Returned * get_relaxed () const { return Funcs::convert (get_stored_relaxed ()); }
+  Returned * get_unconst () const { return const_cast<Returned *> (Funcs::convert (get_stored ())); }
+
+  /* To be possibly overloaded by subclasses. */
+  static Returned* convert (Stored *p) { return p; }
+
+  /* By default null/init/fini the object. */
+  static const Stored* get_null () { return &Null(Stored); }
+  static Stored *create (Data *data)
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init (data);
+    return p;
+  }
+  static Stored *create ()
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init ();
+    return p;
+  }
+  static void destroy (Stored *p)
+  {
+    p->fini ();
+    free (p);
+  }
+
+//  private:
+  /* Must only have one pointer. */
+  hb_atomic_ptr_t<Stored *> instance;
+};
+
+/* Specializations. */
+
+template <typename T, unsigned int WheresFace>
+struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
+                                               hb_face_lazy_loader_t<T, WheresFace>,
+                                               hb_face_t, WheresFace> {};
+
+template <typename T, unsigned int WheresFace>
+struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
+                                                hb_table_lazy_loader_t<T, WheresFace>,
+                                                hb_face_t, WheresFace,
+                                                hb_blob_t>
+{
+  static hb_blob_t *create (hb_face_t *face)
+  { return hb_sanitize_context_t ().reference_table<T> (face); }
+  static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
+
+  static const hb_blob_t *get_null ()
+  { return hb_blob_get_empty (); }
+
+  static const T* convert (const hb_blob_t *blob)
+  { return blob->as<T> (); }
+
+  hb_blob_t* get_blob () const { return this->get_stored (); }
+};
+
+template <typename Subclass>
+struct hb_font_funcs_lazy_loader_t : hb_lazy_loader_t<hb_font_funcs_t, Subclass>
+{
+  static void destroy (hb_font_funcs_t *p)
+  { hb_font_funcs_destroy (p); }
+  static const hb_font_funcs_t *get_null ()
+  { return hb_font_funcs_get_empty (); }
+};
+template <typename Subclass>
+struct hb_unicode_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unicode_funcs_t, Subclass>
+{
+  static void destroy (hb_unicode_funcs_t *p)
+  { hb_unicode_funcs_destroy (p); }
+  static const hb_unicode_funcs_t *get_null ()
+  { return hb_unicode_funcs_get_empty (); }
+};
+
+
+#endif /* HB_MACHINERY_HH */
diff --git a/src/hb-map-private.hh b/src/hb-map-private.hh
deleted file mode 100644 (file)
index d3d4dde..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_MAP_PRIVATE_HH
-#define HB_MAP_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-template <typename T>
-inline uint32_t Hash (const T &v)
-{
-  /* Knuth's multiplicative method: */
-  return (uint32_t) v * 2654435761u;
-}
-
-
-/*
- * hb_map_t
- */
-
-struct hb_map_t
-{
-  struct item_t
-  {
-    hb_codepoint_t key;
-    hb_codepoint_t value;
-
-    inline bool is_unused (void) const { return key == INVALID; }
-    inline bool is_tombstone (void) const { return key != INVALID && value == INVALID; }
-  };
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  unsigned int population; /* Not including tombstones. */
-  unsigned int occupancy; /* Including tombstones. */
-  unsigned int mask;
-  unsigned int prime;
-  item_t *items;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = occupancy = 0;
-    mask = 0;
-    prime = 0;
-    items = nullptr;
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    free (items);
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (void)
-  {
-    if (unlikely (!successful)) return false;
-
-    unsigned int power = _hb_bit_storage (population * 2 + 8);
-    unsigned int new_size = 1u << power;
-    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
-    if (unlikely (!new_items))
-    {
-      successful = false;
-      return false;
-    }
-    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
-
-    unsigned int old_size = mask + 1;
-    item_t *old_items = items;
-
-    /* Switch to new, empty, array. */
-    population = occupancy = 0;
-    mask = new_size - 1;
-    prime = prime_for (power);
-    items = new_items;
-
-    /* Insert back old items. */
-    if (old_items)
-      for (unsigned int i = 0; i < old_size; i++)
-       if (old_items[i].key != INVALID && old_items[i].value != INVALID)
-         set (old_items[i].key, old_items[i].value);
-
-    free (old_items);
-
-    return true;
-  }
-
-  inline void set (hb_codepoint_t key, hb_codepoint_t value)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (key == INVALID)) return;
-    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
-    unsigned int i = bucket_for (key);
-
-    if (value == INVALID && items[i].key != key)
-      return; /* Trying to delete non-existent key. */
-
-    if (!items[i].is_unused ())
-    {
-      occupancy--;
-      if (items[i].is_tombstone ())
-       population--;
-    }
-
-    items[i].key = key;
-    items[i].value = value;
-
-    occupancy++;
-    if (!items[i].is_tombstone ())
-      population++;
-
-  }
-  inline hb_codepoint_t get (hb_codepoint_t key) const
-  {
-    if (unlikely (!items)) return INVALID;
-    unsigned int i = bucket_for (key);
-    return items[i].key == key ? items[i].value : INVALID;
-  }
-
-  inline void del (hb_codepoint_t key)
-  {
-    set (key, INVALID);
-  }
-  inline bool has (hb_codepoint_t key) const
-  {
-    return get (key) != INVALID;
-  }
-
-  inline hb_codepoint_t operator [] (unsigned int key) const
-  { return get (key); }
-
-  static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
-
-  inline void clear (void)
-  {
-    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
-    population = occupancy = 0;
-  }
-
-  inline bool is_empty (void) const
-  {
-    return population != 0;
-  }
-
-  inline unsigned int get_population () const
-  {
-    return population;
-  }
-
-  protected:
-
-  inline unsigned int bucket_for (hb_codepoint_t key) const
-  {
-    unsigned int i = Hash (key) % prime;
-    unsigned int step = 0;
-    unsigned int tombstone = INVALID;
-    while (!items[i].is_unused ())
-    {
-      if (items[i].key == key)
-        return i;
-      if (tombstone == INVALID && items[i].is_tombstone ())
-        tombstone = i;
-      i = (i + ++step) & mask;
-    }
-    return tombstone == INVALID ? i : tombstone;
-  }
-
-  static inline unsigned int prime_for (unsigned int shift)
-  {
-    /* Following comment and table copied from glib. */
-    /* Each table size has an associated prime modulo (the first prime
-     * lower than the table size) used to find the initial bucket. Probing
-     * then works modulo 2^n. The prime modulo is necessary to get a
-     * good distribution with poor hash functions.
-     */
-    /* Not declaring static to make all kinds of compilers happy... */
-    /*static*/ const unsigned int prime_mod [32] =
-    {
-      1,          /* For 1 << 0 */
-      2,
-      3,
-      7,
-      13,
-      31,
-      61,
-      127,
-      251,
-      509,
-      1021,
-      2039,
-      4093,
-      8191,
-      16381,
-      32749,
-      65521,      /* For 1 << 16 */
-      131071,
-      262139,
-      524287,
-      1048573,
-      2097143,
-      4194301,
-      8388593,
-      16777213,
-      33554393,
-      67108859,
-      134217689,
-      268435399,
-      536870909,
-      1073741789,
-      2147483647  /* For 1 << 31 */
-    };
-
-    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
-      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
-
-    return prime_mod[shift];
-  }
-};
-
-
-#endif /* HB_MAP_PRIVATE_HH */
index e3ddae4..a2c770c 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-map
+ * @title: hb-map
+ * @short_description: Object representing integer to integer mapping
+ * @include: hb.h
+ *
+ * Map objects are integer-to-integer hash-maps.  Currently they are
+ * not used in the HarfBuzz public API, but are provided for client's
+ * use if desired.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_create (void)
+hb_map_create ()
 {
   hb_map_t *map;
 
@@ -58,7 +67,7 @@ hb_map_create (void)
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_get_empty (void)
+hb_map_get_empty ()
 {
   return const_cast<hb_map_t *> (&Null(hb_map_t));
 }
@@ -157,8 +166,6 @@ hb_map_allocation_successful (const hb_map_t  *map)
  *
  *
  *
- * Return value:
- *
  * Since: 1.7.7
  **/
 void
@@ -188,7 +195,7 @@ hb_map_get (const hb_map_t *map,
 /**
  * hb_map_del:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
@@ -204,7 +211,7 @@ hb_map_del (hb_map_t       *map,
 /**
  * hb_map_has:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
diff --git a/src/hb-map.hh b/src/hb-map.hh
new file mode 100644 (file)
index 0000000..02d5406
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MAP_HH
+#define HB_MAP_HH
+
+#include "hb.hh"
+
+
+template <typename T>
+inline uint32_t Hash (const T &v)
+{
+  /* Knuth's multiplicative method: */
+  return (uint32_t) v * 2654435761u;
+}
+
+
+/*
+ * hb_map_t
+ */
+
+struct hb_map_t
+{
+  HB_NO_COPY_ASSIGN (hb_map_t);
+  hb_map_t ()  { init (); }
+  ~hb_map_t () { fini (); }
+
+  struct item_t
+  {
+    hb_codepoint_t key;
+    hb_codepoint_t value;
+
+    bool is_unused () const    { return key == INVALID; }
+    bool is_tombstone () const { return key != INVALID && value == INVALID; }
+  };
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  unsigned int population; /* Not including tombstones. */
+  unsigned int occupancy; /* Including tombstones. */
+  unsigned int mask;
+  unsigned int prime;
+  item_t *items;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = occupancy = 0;
+    mask = 0;
+    prime = 0;
+    items = nullptr;
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    free (items);
+    items = nullptr;
+  }
+  void fini ()
+  {
+    population = occupancy = 0;
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize ()
+  {
+    if (unlikely (!successful)) return false;
+
+    unsigned int power = hb_bit_storage (population * 2 + 8);
+    unsigned int new_size = 1u << power;
+    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
+    if (unlikely (!new_items))
+    {
+      successful = false;
+      return false;
+    }
+    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
+
+    unsigned int old_size = mask + 1;
+    item_t *old_items = items;
+
+    /* Switch to new, empty, array. */
+    population = occupancy = 0;
+    mask = new_size - 1;
+    prime = prime_for (power);
+    items = new_items;
+
+    /* Insert back old items. */
+    if (old_items)
+      for (unsigned int i = 0; i < old_size; i++)
+       if (old_items[i].key != INVALID && old_items[i].value != INVALID)
+         set (old_items[i].key, old_items[i].value);
+
+    free (old_items);
+
+    return true;
+  }
+
+  void set (hb_codepoint_t key, hb_codepoint_t value)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (key == INVALID)) return;
+    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
+    unsigned int i = bucket_for (key);
+
+    if (value == INVALID && items[i].key != key)
+      return; /* Trying to delete non-existent key. */
+
+    if (!items[i].is_unused ())
+    {
+      occupancy--;
+      if (items[i].is_tombstone ())
+       population--;
+    }
+
+    items[i].key = key;
+    items[i].value = value;
+
+    occupancy++;
+    if (!items[i].is_tombstone ())
+      population++;
+
+  }
+  hb_codepoint_t get (hb_codepoint_t key) const
+  {
+    if (unlikely (!items)) return INVALID;
+    unsigned int i = bucket_for (key);
+    return items[i].key == key ? items[i].value : INVALID;
+  }
+
+  void del (hb_codepoint_t key) { set (key, INVALID); }
+
+  bool has (hb_codepoint_t key) const
+  { return get (key) != INVALID; }
+
+  hb_codepoint_t operator [] (unsigned int key) const
+  { return get (key); }
+
+  static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
+
+  void clear ()
+  {
+    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
+    population = occupancy = 0;
+  }
+
+  bool is_empty () const { return population == 0; }
+
+  unsigned int get_population () const { return population; }
+
+  protected:
+
+  unsigned int bucket_for (hb_codepoint_t key) const
+  {
+    unsigned int i = Hash (key) % prime;
+    unsigned int step = 0;
+    unsigned int tombstone = INVALID;
+    while (!items[i].is_unused ())
+    {
+      if (items[i].key == key)
+        return i;
+      if (tombstone == INVALID && items[i].is_tombstone ())
+        tombstone = i;
+      i = (i + ++step) & mask;
+    }
+    return tombstone == INVALID ? i : tombstone;
+  }
+
+  static unsigned int prime_for (unsigned int shift)
+  {
+    /* Following comment and table copied from glib. */
+    /* Each table size has an associated prime modulo (the first prime
+     * lower than the table size) used to find the initial bucket. Probing
+     * then works modulo 2^n. The prime modulo is necessary to get a
+     * good distribution with poor hash functions.
+     */
+    /* Not declaring static to make all kinds of compilers happy... */
+    /*static*/ const unsigned int prime_mod [32] =
+    {
+      1,          /* For 1 << 0 */
+      2,
+      3,
+      7,
+      13,
+      31,
+      61,
+      127,
+      251,
+      509,
+      1021,
+      2039,
+      4093,
+      8191,
+      16381,
+      32749,
+      65521,      /* For 1 << 16 */
+      131071,
+      262139,
+      524287,
+      1048573,
+      2097143,
+      4194301,
+      8388593,
+      16777213,
+      33554393,
+      67108859,
+      134217689,
+      268435399,
+      536870909,
+      1073741789,
+      2147483647  /* For 1 << 31 */
+    };
+
+    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
+      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
+
+    return prime_mod[shift];
+  }
+};
+
+
+#endif /* HB_MAP_HH */
diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
deleted file mode 100644 (file)
index 14bde31..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,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.
- *
- * Contributor(s):
- *     Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_MUTEX_PRIVATE_HH
-#define HB_MUTEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* mutex */
-
-/* We need external help for these */
-
-#if defined(HB_MUTEX_IMPL_INIT) \
- && defined(hb_mutex_impl_init) \
- && defined(hb_mutex_impl_lock) \
- && defined(hb_mutex_impl_unlock) \
- && defined(hb_mutex_impl_finish)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-typedef CRITICAL_SECTION hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT     {0}
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#define hb_mutex_impl_init(M)  InitializeCriticalSectionEx (M, 0, 0)
-#else
-#define hb_mutex_impl_init(M)  InitializeCriticalSection (M)
-#endif
-#define hb_mutex_impl_lock(M)  EnterCriticalSection (M)
-#define hb_mutex_impl_unlock(M)        LeaveCriticalSection (M)
-#define hb_mutex_impl_finish(M)        DeleteCriticalSection (M)
-
-
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-
-#include <pthread.h>
-typedef pthread_mutex_t hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT     PTHREAD_MUTEX_INITIALIZER
-#define hb_mutex_impl_init(M)  pthread_mutex_init (M, nullptr)
-#define hb_mutex_impl_lock(M)  pthread_mutex_lock (M)
-#define hb_mutex_impl_unlock(M)        pthread_mutex_unlock (M)
-#define hb_mutex_impl_finish(M)        pthread_mutex_destroy (M)
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-/* This actually is not a totally awful implementation. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT     0
-#define hb_mutex_impl_init(M)  *(M) = 0
-#define hb_mutex_impl_lock(M)  HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
-#define hb_mutex_impl_unlock(M)        __sync_lock_release (M)
-#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
-
-
-#elif !defined(HB_NO_MT)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT     0
-#define hb_mutex_impl_init(M)  *(M) = 0
-#define hb_mutex_impl_lock(M)  HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
-#define hb_mutex_impl_unlock(M)        (*(M))--;
-#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT     0
-#define hb_mutex_impl_init(M)  HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_lock(M)  HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_unlock(M)        HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
-
-
-#endif
-
-
-#define HB_MUTEX_INIT          {HB_MUTEX_IMPL_INIT}
-
-struct hb_mutex_t
-{
-  /* TODO Add tracing. */
-
-  hb_mutex_impl_t m;
-
-  inline void init   (void) { hb_mutex_impl_init   (&m); }
-  inline void lock   (void) { hb_mutex_impl_lock   (&m); }
-  inline void unlock (void) { hb_mutex_impl_unlock (&m); }
-  inline void fini (void) { hb_mutex_impl_finish (&m); }
-};
-
-
-#endif /* HB_MUTEX_PRIVATE_HH */
diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh
new file mode 100644 (file)
index 0000000..35f1fde
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,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.
+ *
+ * Contributor(s):
+ *     Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MUTEX_HH
+#define HB_MUTEX_HH
+
+#include "hb.hh"
+
+
+/* mutex */
+
+/* We need external help for these */
+
+#if defined(HB_MUTEX_IMPL_INIT) \
+ && defined(hb_mutex_impl_init) \
+ && defined(hb_mutex_impl_lock) \
+ && defined(hb_mutex_impl_unlock) \
+ && defined(hb_mutex_impl_finish)
+
+/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+typedef CRITICAL_SECTION hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     {0}
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M)  InitializeCriticalSectionEx (M, 0, 0)
+#else
+#define hb_mutex_impl_init(M)  InitializeCriticalSection (M)
+#endif
+#define hb_mutex_impl_lock(M)  EnterCriticalSection (M)
+#define hb_mutex_impl_unlock(M)        LeaveCriticalSection (M)
+#define hb_mutex_impl_finish(M)        DeleteCriticalSection (M)
+
+
+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+
+#include <pthread.h>
+typedef pthread_mutex_t hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     PTHREAD_MUTEX_INITIALIZER
+#define hb_mutex_impl_init(M)  pthread_mutex_init (M, nullptr)
+#define hb_mutex_impl_lock(M)  pthread_mutex_lock (M)
+#define hb_mutex_impl_unlock(M)        pthread_mutex_unlock (M)
+#define hb_mutex_impl_finish(M)        pthread_mutex_destroy (M)
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+/* This actually is not a totally awful implementation. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     0
+#define hb_mutex_impl_init(M)  *(M) = 0
+#define hb_mutex_impl_lock(M)  HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
+#define hb_mutex_impl_unlock(M)        __sync_lock_release (M)
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
+
+
+#elif !defined(HB_NO_MT)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     0
+#define hb_mutex_impl_init(M)  *(M) = 0
+#define hb_mutex_impl_lock(M)  HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
+#define hb_mutex_impl_unlock(M)        (*(M))--;
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
+
+
+#else /* HB_NO_MT */
+
+typedef int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     0
+#define hb_mutex_impl_init(M)  HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_lock(M)  HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_unlock(M)        HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
+
+
+#endif
+
+
+#define HB_MUTEX_INIT          {HB_MUTEX_IMPL_INIT}
+
+struct hb_mutex_t
+{
+  /* TODO Add tracing. */
+
+  hb_mutex_impl_t m;
+
+  void init   () { hb_mutex_impl_init   (&m); }
+  void lock   () { hb_mutex_impl_lock   (&m); }
+  void unlock () { hb_mutex_impl_unlock (&m); }
+  void fini ()   { hb_mutex_impl_finish (&m); }
+};
+
+struct hb_lock_t
+{
+  hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
+  ~hb_lock_t () { mutex.unlock (); }
+  private:
+  hb_mutex_t &mutex;
+};
+
+
+#endif /* HB_MUTEX_HH */
diff --git a/src/hb-null.hh b/src/hb-null.hh
new file mode 100644 (file)
index 0000000..204c2fe
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_NULL_HH
+#define HB_NULL_HH
+
+#include "hb.hh"
+
+
+/*
+ * Static pools
+ */
+
+/* Global nul-content Null pool.  Enlarge as necessary. */
+
+#define HB_NULL_POOL_SIZE 9880
+
+/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
+ * otherwise return sizeof(T). */
+
+/* The hard way...
+ * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
+ */
+
+template<bool> struct _hb_bool_type {};
+
+template <typename T, typename B>
+struct _hb_null_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::null_size }; };
+
+template <typename T>
+struct hb_null_size
+{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
+#define hb_null_size(T) hb_null_size<T>::value
+
+/* These doesn't belong here, but since is copy/paste from above, put it here. */
+
+/* hb_static_size (T)
+ * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
+
+template <typename T, typename B>
+struct _hb_static_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::static_size }; };
+
+template <typename T>
+struct hb_static_size
+{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
+#define hb_static_size(T) hb_static_size<T>::value
+
+
+/* hb_assign (obj, value)
+ * Calls obj.set (value) if obj.min_size is defined and value has different type
+ * from obj, or obj = v otherwise. */
+
+template <typename T, typename V, typename B>
+struct _hb_assign
+{ static inline void value (T &o, const V v) { o = v; } };
+template <typename T, typename V>
+struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const V v) { o.set (v); } };
+template <typename T>
+struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const T v) { o = v; } };
+
+template <typename T, typename V>
+static inline void hb_assign (T &o, const V v)
+{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); }
+
+
+/*
+ * Null()
+ */
+
+extern HB_INTERNAL
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* Generic nul-content Null objects. */
+template <typename Type>
+static inline Type const & Null () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  return *reinterpret_cast<Type const *> (_hb_NullPool);
+}
+template <typename QType>
+struct NullHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static const Type & get_null () { return Null<Type> (); }
+};
+#define Null(Type) NullHelper<Type>::get_null ()
+
+/* Specializations for arbitrary-content Null objects expressed in bytes. */
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+       } /* Close namespace. */ \
+       extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+       template <> \
+       /*static*/ inline const Namespace::Type& Null<Namespace::Type> () { \
+         return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+       } \
+       namespace Namespace { \
+       static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+       const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+
+/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
+#define DECLARE_NULL_INSTANCE(Type) \
+       extern HB_INTERNAL const Type _hb_Null_##Type; \
+       template <> \
+       /*static*/ inline const Type& Null<Type> () { \
+         return _hb_Null_##Type; \
+       } \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_INSTANCE(Type) \
+       const Type _hb_Null_##Type
+
+/* Global writable pool.  Enlarge as necessary. */
+
+/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
+ * for correct operation. It only exist to catch and divert program logic bugs instead of
+ * causing bad memory access. So, races there are not actually introducing incorrectness
+ * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
+extern HB_INTERNAL
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* CRAP pool: Common Region for Access Protection. */
+template <typename Type>
+static inline Type& Crap () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
+  memcpy (obj, &Null(Type), sizeof (*obj));
+  return *obj;
+}
+template <typename QType>
+struct CrapHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static Type & get_crap () { return Crap<Type> (); }
+};
+#define Crap(Type) CrapHelper<Type>::get_crap ()
+
+template <typename Type>
+struct CrapOrNullHelper {
+  static Type & get () { return Crap(Type); }
+};
+template <typename Type>
+struct CrapOrNullHelper<const Type> {
+  static const Type & get () { return Null(Type); }
+};
+#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
+
+
+/*
+ * hb_nonnull_ptr_t
+ */
+
+template <typename P>
+struct hb_nonnull_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
+  T * operator = (T *v_)   { return v = v_; }
+  T * operator -> () const { return get (); }
+  T & operator * () const  { return *get (); }
+  T ** operator & () const { return &v; }
+  /* Only auto-cast to const types. */
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  T * get () const { return v ? v : const_cast<T *> (&Null(T)); }
+  T * get_raw () const { return v; }
+
+  T *v;
+};
+
+
+#endif /* HB_NULL_HH */
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
deleted file mode 100644 (file)
index fc48a91..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,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.
- *
- * Contributor(s):
- *     Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OBJECT_PRIVATE_HH
-#define HB_OBJECT_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
-
-/* reference_count */
-
-#define HB_REFERENCE_COUNT_INERT_VALUE 0
-#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
-#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
-
-struct hb_reference_count_t
-{
-  hb_atomic_int_t ref_count;
-
-  inline void init (int v) { ref_count.set_unsafe (v); }
-  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
-  inline int inc (void) { return ref_count.inc (); }
-  inline int dec (void) { return ref_count.dec (); }
-  inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
-
-  inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
-  inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
-};
-
-
-/* user_data */
-
-struct hb_user_data_array_t
-{
-  struct hb_user_data_item_t {
-    hb_user_data_key_t *key;
-    void *data;
-    hb_destroy_func_t destroy;
-
-    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
-    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
-
-    void fini (void) { if (destroy) destroy (data); }
-  };
-
-  hb_mutex_t lock;
-  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
-
-  inline void init (void) { lock.init (); items.init (); }
-
-  HB_INTERNAL bool set (hb_user_data_key_t *key,
-                       void *              data,
-                       hb_destroy_func_t   destroy,
-                       hb_bool_t           replace);
-
-  HB_INTERNAL void *get (hb_user_data_key_t *key);
-
-  inline void fini (void) { items.fini (lock); lock.fini (); }
-};
-
-
-/* object_header */
-
-struct hb_object_header_t
-{
-  hb_reference_count_t ref_count;
-  hb_user_data_array_t *user_data;
-
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
-
-  private:
-  ASSERT_POD ();
-};
-
-
-/* object */
-
-template <typename Type>
-static inline void hb_object_trace (const Type *obj, const char *function)
-{
-  DEBUG_MSG (OBJECT, (void *) obj,
-            "%s refcount=%d",
-            function,
-            obj ? obj->header.ref_count.get_unsafe () : 0);
-}
-
-template <typename Type>
-static inline Type *hb_object_create (void)
-{
-  Type *obj = (Type *) calloc (1, sizeof (Type));
-
-  if (unlikely (!obj))
-    return obj;
-
-  hb_object_init (obj);
-  hb_object_trace (obj, HB_FUNC);
-  return obj;
-}
-template <typename Type>
-static inline void hb_object_init (Type *obj)
-{
-  obj->header.ref_count.init (1);
-  obj->header.user_data = nullptr;
-}
-template <typename Type>
-static inline bool hb_object_is_inert (const Type *obj)
-{
-  return unlikely (obj->header.ref_count.is_inert ());
-}
-template <typename Type>
-static inline bool hb_object_is_valid (const Type *obj)
-{
-  return likely (obj->header.ref_count.is_valid ());
-}
-template <typename Type>
-static inline Type *hb_object_reference (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return obj;
-  assert (hb_object_is_valid (obj));
-  obj->header.ref_count.inc ();
-  return obj;
-}
-template <typename Type>
-static inline bool hb_object_destroy (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-  if (obj->header.ref_count.dec () != 1)
-    return false;
-
-  hb_object_fini (obj);
-  return true;
-}
-template <typename Type>
-static inline void hb_object_fini (Type *obj)
-{
-  obj->header.ref_count.fini (); /* Do this before user_data */
-  if (obj->header.user_data)
-  {
-    obj->header.user_data->fini ();
-    free (obj->header.user_data);
-  }
-}
-template <typename Type>
-static inline bool hb_object_set_user_data (Type               *obj,
-                                           hb_user_data_key_t *key,
-                                           void *              data,
-                                           hb_destroy_func_t   destroy,
-                                           hb_bool_t           replace)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-
-retry:
-  hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data);
-  if (unlikely (!user_data))
-  {
-    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
-    if (unlikely (!user_data))
-      return false;
-    user_data->init ();
-    if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data)))
-    {
-      user_data->fini ();
-      free (user_data);
-      goto retry;
-    }
-  }
-
-  return user_data->set (key, data, destroy, replace);
-}
-
-template <typename Type>
-static inline void *hb_object_get_user_data (Type               *obj,
-                                            hb_user_data_key_t *key)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data))
-    return nullptr;
-  assert (hb_object_is_valid (obj));
-  return obj->header.user_data->get (key);
-}
-
-
-#endif /* HB_OBJECT_PRIVATE_HH */
diff --git a/src/hb-object.hh b/src/hb-object.hh
new file mode 100644 (file)
index 0000000..68520f2
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,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.
+ *
+ * Contributor(s):
+ *     Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OBJECT_HH
+#define HB_OBJECT_HH
+
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Lockable set
+ */
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+  hb_vector_t<item_t> items;
+
+  void init () { items.init (); }
+
+  template <typename T>
+  item_t *replace_or_insert (T v, lock_t &l, bool replace)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      if (replace) {
+       item_t old = *item;
+       *item = v;
+       l.unlock ();
+       old.fini ();
+      }
+      else {
+        item = nullptr;
+       l.unlock ();
+      }
+    } else {
+      item = items.push (v);
+      l.unlock ();
+    }
+    return item;
+  }
+
+  template <typename T>
+  void remove (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+    {
+      item_t old = *item;
+      *item = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+    } else {
+      l.unlock ();
+    }
+  }
+
+  template <typename T>
+  bool find (T v, item_t *i, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+      *i = *item;
+    l.unlock ();
+    return !!item;
+  }
+
+  template <typename T>
+  item_t *find_or_insert (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push (v);
+    }
+    l.unlock ();
+    return item;
+  }
+
+  void fini (lock_t &l)
+  {
+    if (!items.length)
+    {
+      /* No need to lock. */
+      items.fini ();
+      return;
+    }
+    l.lock ();
+    while (items.length)
+    {
+      item_t old = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+      l.lock ();
+    }
+    items.fini ();
+    l.unlock ();
+  }
+
+};
+
+
+/*
+ * Reference-count.
+ */
+
+#define HB_REFERENCE_COUNT_INERT_VALUE 0
+#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
+#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
+
+struct hb_reference_count_t
+{
+  mutable hb_atomic_int_t ref_count;
+
+  void init (int v = 1) { ref_count.set_relaxed (v); }
+  int get_relaxed () const { return ref_count.get_relaxed (); }
+  int inc () const { return ref_count.inc (); }
+  int dec () const { return ref_count.dec (); }
+  void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
+
+  bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
+  bool is_valid () const { return ref_count.get_relaxed () > 0; }
+};
+
+
+/* user_data */
+
+struct hb_user_data_array_t
+{
+  struct hb_user_data_item_t {
+    hb_user_data_key_t *key;
+    void *data;
+    hb_destroy_func_t destroy;
+
+    bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+    bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
+
+    void fini () { if (destroy) destroy (data); }
+  };
+
+  hb_mutex_t lock;
+  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
+
+  void init () { lock.init (); items.init (); }
+
+  HB_INTERNAL bool set (hb_user_data_key_t *key,
+                       void *              data,
+                       hb_destroy_func_t   destroy,
+                       hb_bool_t           replace);
+
+  HB_INTERNAL void *get (hb_user_data_key_t *key);
+
+  void fini () { items.fini (lock); lock.fini (); }
+};
+
+
+/*
+ * Object header
+ */
+
+struct hb_object_header_t
+{
+  hb_reference_count_t ref_count;
+  mutable hb_atomic_int_t writable;
+  hb_atomic_ptr_t<hb_user_data_array_t> user_data;
+};
+#define HB_OBJECT_HEADER_STATIC \
+       { \
+         HB_REFERENCE_COUNT_INIT, \
+         HB_ATOMIC_INT_INIT (false), \
+         HB_ATOMIC_PTR_INIT (nullptr) \
+       }
+
+
+/*
+ * Object
+ */
+
+template <typename Type>
+static inline void hb_object_trace (const Type *obj, const char *function)
+{
+  DEBUG_MSG (OBJECT, (void *) obj,
+            "%s refcount=%d",
+            function,
+            obj ? obj->header.ref_count.get_relaxed () : 0);
+}
+
+template <typename Type>
+static inline Type *hb_object_create ()
+{
+  Type *obj = (Type *) calloc (1, sizeof (Type));
+
+  if (unlikely (!obj))
+    return obj;
+
+  hb_object_init (obj);
+  hb_object_trace (obj, HB_FUNC);
+  return obj;
+}
+template <typename Type>
+static inline void hb_object_init (Type *obj)
+{
+  obj->header.ref_count.init ();
+  obj->header.writable.set_relaxed (true);
+  obj->header.user_data.init ();
+}
+template <typename Type>
+static inline bool hb_object_is_inert (const Type *obj)
+{
+  return unlikely (obj->header.ref_count.is_inert ());
+}
+template <typename Type>
+static inline bool hb_object_is_valid (const Type *obj)
+{
+  return likely (obj->header.ref_count.is_valid ());
+}
+template <typename Type>
+static inline bool hb_object_is_immutable (const Type *obj)
+{
+  return !obj->header.writable.get_relaxed ();
+}
+template <typename Type>
+static inline void hb_object_make_immutable (const Type *obj)
+{
+  obj->header.writable.set_relaxed (false);
+}
+template <typename Type>
+static inline Type *hb_object_reference (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return obj;
+  assert (hb_object_is_valid (obj));
+  obj->header.ref_count.inc ();
+  return obj;
+}
+template <typename Type>
+static inline bool hb_object_destroy (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+  if (obj->header.ref_count.dec () != 1)
+    return false;
+
+  hb_object_fini (obj);
+  return true;
+}
+template <typename Type>
+static inline void hb_object_fini (Type *obj)
+{
+  obj->header.ref_count.fini (); /* Do this before user_data */
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (user_data)
+  {
+    user_data->fini ();
+    free (user_data);
+    user_data = nullptr;
+  }
+}
+template <typename Type>
+static inline bool hb_object_set_user_data (Type               *obj,
+                                           hb_user_data_key_t *key,
+                                           void *              data,
+                                           hb_destroy_func_t   destroy,
+                                           hb_bool_t           replace)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+
+retry:
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (unlikely (!user_data))
+  {
+    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
+    if (unlikely (!user_data))
+      return false;
+    user_data->init ();
+    if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
+    {
+      user_data->fini ();
+      free (user_data);
+      goto retry;
+    }
+  }
+
+  return user_data->set (key, data, destroy, replace);
+}
+
+template <typename Type>
+static inline void *hb_object_get_user_data (Type               *obj,
+                                            hb_user_data_key_t *key)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return nullptr;
+  assert (hb_object_is_valid (obj));
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (!user_data)
+    return nullptr;
+  return user_data->get (key);
+}
+
+
+#endif /* HB_OBJECT_HH */
diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
deleted file mode 100644 (file)
index 2965b46..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 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
- */
-
-#ifndef HB_OPEN_FILE_PRIVATE_HH
-#define HB_OPEN_FILE_PRIVATE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-head-table.hh"
-
-
-namespace OT {
-
-
-/*
- *
- * The OpenType Font File
- *
- */
-
-
-/*
- * Organization of an OpenType Font
- */
-
-struct OpenTypeFontFile;
-struct OffsetTable;
-struct TTCHeader;
-
-
-typedef struct TableRecord
-{
-  int cmp (Tag t) const
-  { return -t.cmp (tag); }
-
-  static int cmp (const void *pa, const void *pb)
-  {
-    const TableRecord *a = (const TableRecord *) pa;
-    const TableRecord *b = (const TableRecord *) pb;
-    return b->cmp (a->tag);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  Tag          tag;            /* 4-byte identifier. */
-  CheckSum     checkSum;       /* CheckSum for this table. */
-  Offset32     offset;         /* Offset from beginning of TrueType font
-                                * file. */
-  HBUINT32     length;         /* Length of this table. */
-  public:
-  DEFINE_SIZE_STATIC (16);
-} OpenTypeTable;
-
-typedef struct OffsetTable
-{
-  friend struct OpenTypeFontFile;
-
-  inline unsigned int get_table_count (void) const
-  { return tables.len; }
-  inline const TableRecord& get_table (unsigned int i) const
-  {
-    return tables[i];
-  }
-  inline unsigned int get_table_tags (unsigned int  start_offset,
-                                     unsigned int *table_count, /* IN/OUT */
-                                     hb_tag_t     *table_tags /* OUT */) const
-  {
-    if (table_count)
-    {
-      if (start_offset >= tables.len)
-        *table_count = 0;
-      else
-        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
-
-      const TableRecord *sub_tables = tables.arrayZ + start_offset;
-      unsigned int count = *table_count;
-      for (unsigned int i = 0; i < count; i++)
-       table_tags[i] = sub_tables[i].tag;
-    }
-    return tables.len;
-  }
-  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
-  {
-    Tag t;
-    t.set (tag);
-    /* Linear-search for small tables to work around fonts with unsorted
-     * table list. */
-    int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
-    if (table_index)
-      *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
-    return i != -1;
-  }
-  inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
-  {
-    unsigned int table_index;
-    find_table_index (tag, &table_index);
-    return get_table (table_index);
-  }
-
-  public:
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        hb_tag_t sfnt_tag,
-                        Supplier<hb_tag_t> &tags,
-                        Supplier<hb_blob_t *> &blobs,
-                        unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    /* Alloc 12 for the OTHeader. */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3). */
-    sfnt_version.set (sfnt_tag);
-    /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
-
-    const char *dir_end = (const char *) c->head;
-    HBUINT32 *checksum_adjustment = nullptr;
-
-    /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < table_count; i++)
-    {
-      TableRecord &rec = tables.arrayZ[i];
-      hb_blob_t *blob = blobs[i];
-      rec.tag.set (tags[i]);
-      rec.length.set (hb_blob_get_length (blob));
-      rec.offset.serialize (c, this);
-
-      /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (rec.length);
-      if (unlikely (!start)) {return false;}
-
-      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
-
-      /* 4-byte allignment. */
-      if (rec.length % 4)
-       c->allocate_size<void> (4 - rec.length % 4);
-      const char *end = (const char *) c->head;
-
-      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
-      {
-       head *h = (head *) start;
-       checksum_adjustment = &h->checkSumAdjustment;
-       checksum_adjustment->set (0);
-      }
-
-      rec.checkSum.set_for_data (start, end - start);
-    }
-    tags += table_count;
-    blobs += table_count;
-
-    tables.qsort ();
-
-    if (checksum_adjustment)
-    {
-      CheckSum checksum;
-
-      /* The following line is a slower version of the following block. */
-      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
-      checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < table_count; i++)
-      {
-       TableRecord &rec = tables.arrayZ[i];
-       checksum.set (checksum + rec.checkSum);
-      }
-
-      checksum_adjustment->set (0xB1B0AFBAu - checksum);
-    }
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && tables.sanitize (c));
-  }
-
-  protected:
-  Tag          sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
-  BinSearchArrayOf<TableRecord>
-               tables;
-  public:
-  DEFINE_SIZE_ARRAY (12, tables);
-} OpenTypeFontFace;
-
-
-/*
- * TrueType Collections
- */
-
-struct TTCHeaderVersion1
-{
-  friend struct TTCHeader;
-
-  inline unsigned int get_face_count (void) const { return table.len; }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (table.sanitize (c, this));
-  }
-
-  protected:
-  Tag          ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;       /* Version of the TTC Header (1.0),
-                                * 0x00010000u */
-  LArrayOf<LOffsetTo<OffsetTable> >
-               table;          /* Array of offsets to the OffsetTable for each font
-                                * from the beginning of the file */
-  public:
-  DEFINE_SIZE_ARRAY (12, table);
-};
-
-struct TTCHeader
-{
-  friend struct OpenTypeFontFile;
-
-  private:
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face_count ();
-    default:return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face (i);
-    default:return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return_trace (u.version1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  struct {
-  Tag          ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;       /* Version of the TTC Header (1.0 or 2.0),
-                                * 0x00010000u or 0x00020000u */
-  }                    header;
-  TTCHeaderVersion1    version1;
-  } u;
-};
-
-
-/*
- * OpenType Font File
- */
-
-struct OpenTypeFontFile
-{
-  static const hb_tag_t tableTag       = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
-
-  enum {
-    CFFTag             = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
-    TrueTypeTag        = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
-    TTCTag             = HB_TAG ('t','t','c','f'), /* TrueType Collection */
-    TrueTag            = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
-    Typ1Tag            = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
-  };
-
-  inline hb_tag_t get_tag (void) const { return u.tag; }
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.tag) {
-    case CFFTag:       /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:  return 1;
-    case TTCTag:       return u.ttcHeader.get_face_count ();
-    default:           return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.tag) {
-    /* Note: for non-collection SFNT data we ignore index.  This is because
-     * Apple dfont container is a container of SFNT's.  So each SFNT is a
-     * non-TTC, but the index is more than zero. */
-    case CFFTag:       /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:  return u.fontFace;
-    case TTCTag:       return u.ttcHeader.get_face (i);
-    default:           return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool serialize_single (hb_serialize_context_t *c,
-                               hb_tag_t sfnt_tag,
-                               Supplier<hb_tag_t> &tags,
-                               Supplier<hb_blob_t *> &blobs,
-                               unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    assert (sfnt_tag != TTCTag);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
-    switch (u.tag) {
-    case CFFTag:       /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:  return_trace (u.fontFace.sanitize (c));
-    case TTCTag:       return_trace (u.ttcHeader.sanitize (c));
-    default:           return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  Tag                  tag;            /* 4-byte identifier. */
-  OpenTypeFontFace     fontFace;
-  TTCHeader            ttcHeader;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (4, tag);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_FILE_PRIVATE_HH */
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
new file mode 100644 (file)
index 0000000..32a223c
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 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
+ */
+
+#ifndef HB_OPEN_FILE_HH
+#define HB_OPEN_FILE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-head-table.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File
+ *
+ */
+
+
+/*
+ * Organization of an OpenType Font
+ */
+
+struct OpenTypeFontFile;
+struct OffsetTable;
+struct TTCHeader;
+
+
+typedef struct TableRecord
+{
+  int cmp (Tag t) const { return -t.cmp (tag); }
+
+  static int cmp (const void *pa, const void *pb)
+  {
+    const TableRecord *a = (const TableRecord *) pa;
+    const TableRecord *b = (const TableRecord *) pb;
+    return b->cmp (a->tag);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Tag          tag;            /* 4-byte identifier. */
+  CheckSum     checkSum;       /* CheckSum for this table. */
+  Offset32     offset;         /* Offset from beginning of TrueType font
+                                * file. */
+  HBUINT32     length;         /* Length of this table. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+} OpenTypeTable;
+
+typedef struct OffsetTable
+{
+  friend struct OpenTypeFontFile;
+
+  unsigned int get_table_count () const { return tables.len; }
+  const TableRecord& get_table (unsigned int i) const
+  { return tables[i]; }
+  unsigned int get_table_tags (unsigned int  start_offset,
+                                     unsigned int *table_count, /* IN/OUT */
+                                     hb_tag_t     *table_tags /* OUT */) const
+  {
+    if (table_count)
+    {
+      if (start_offset >= tables.len)
+        *table_count = 0;
+      else
+        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
+
+      const TableRecord *sub_tables = tables.arrayZ + start_offset;
+      unsigned int count = *table_count;
+      for (unsigned int i = 0; i < count; i++)
+       table_tags[i] = sub_tables[i].tag;
+    }
+    return tables.len;
+  }
+  bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
+  {
+    Tag t;
+    t.set (tag);
+    return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+  const TableRecord& get_table_by_tag (hb_tag_t tag) const
+  {
+    unsigned int table_index;
+    find_table_index (tag, &table_index);
+    return get_table (table_index);
+  }
+
+  public:
+
+  template <typename item_t>
+  bool serialize (hb_serialize_context_t *c,
+                 hb_tag_t sfnt_tag,
+                 hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    /* Alloc 12 for the OTHeader. */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    /* Write sfntVersion (bytes 0..3). */
+    sfnt_version.set (sfnt_tag);
+    /* Take space for numTables, searchRange, entrySelector, RangeShift
+     * and the TableRecords themselves.  */
+    if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
+
+    const char *dir_end = (const char *) c->head;
+    HBUINT32 *checksum_adjustment = nullptr;
+
+    /* Write OffsetTables, alloc for and write actual table blobs. */
+    for (unsigned int i = 0; i < tables.len; i++)
+    {
+      TableRecord &rec = tables.arrayZ[i];
+      hb_blob_t *blob = items[i].blob;
+      rec.tag.set (items[i].tag);
+      rec.length.set (hb_blob_get_length (blob));
+      rec.offset.serialize (c, this);
+
+      /* Allocate room for the table and copy it. */
+      char *start = (char *) c->allocate_size<void> (rec.length);
+      if (unlikely (!start)) {return false;}
+
+      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
+
+      /* 4-byte alignment. */
+      c->align (4);
+      const char *end = (const char *) c->head;
+
+      if (items[i].tag == HB_OT_TAG_head &&
+         (unsigned) (end - start) >= head::static_size)
+      {
+       head *h = (head *) start;
+       checksum_adjustment = &h->checkSumAdjustment;
+       checksum_adjustment->set (0);
+      }
+
+      rec.checkSum.set_for_data (start, end - start);
+    }
+
+    tables.qsort ();
+
+    if (checksum_adjustment)
+    {
+      CheckSum checksum;
+
+      /* The following line is a slower version of the following block. */
+      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
+      checksum.set_for_data (this, dir_end - (const char *) this);
+      for (unsigned int i = 0; i < items.length; i++)
+      {
+       TableRecord &rec = tables.arrayZ[i];
+       checksum.set (checksum + rec.checkSum);
+      }
+
+      checksum_adjustment->set (0xB1B0AFBAu - checksum);
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && tables.sanitize (c));
+  }
+
+  protected:
+  Tag          sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
+  BinSearchArrayOf<TableRecord>
+               tables;
+  public:
+  DEFINE_SIZE_ARRAY (12, tables);
+} OpenTypeFontFace;
+
+
+/*
+ * TrueType Collections
+ */
+
+struct TTCHeaderVersion1
+{
+  friend struct TTCHeader;
+
+  unsigned int get_face_count () const { return table.len; }
+  const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (table.sanitize (c, this));
+  }
+
+  protected:
+  Tag          ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;       /* Version of the TTC Header (1.0),
+                                * 0x00010000u */
+  LArrayOf<LOffsetTo<OffsetTable> >
+               table;          /* Array of offsets to the OffsetTable for each font
+                                * from the beginning of the file */
+  public:
+  DEFINE_SIZE_ARRAY (12, table);
+};
+
+struct TTCHeader
+{
+  friend struct OpenTypeFontFile;
+
+  private:
+
+  unsigned int get_face_count () const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face_count ();
+    default:return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i) const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face (i);
+    default:return Null(OpenTypeFontFace);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return_trace (u.version1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  struct {
+  Tag          ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;       /* Version of the TTC Header (1.0 or 2.0),
+                                * 0x00010000u or 0x00020000u */
+  }                    header;
+  TTCHeaderVersion1    version1;
+  } u;
+};
+
+/*
+ * Mac Resource Fork
+ *
+ * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
+ */
+
+struct ResourceRecord
+{
+  const OpenTypeFontFace & get_face (const void *data_base) const
+  { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                       const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 offset.sanitize (c, data_base) &&
+                 get_face (data_base).sanitize (c));
+  }
+
+  protected:
+  HBUINT16     id;             /* Resource ID. */
+  HBINT16      nameOffset;     /* Offset from beginning of resource name list
+                                * to resource name, -1 means there is none. */
+  HBUINT8      attrs;          /* Resource attributes */
+  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
+               offset;         /* Offset from beginning of data block to
+                                * data for this resource */
+  HBUINT32     reserved;       /* Reserved for handle to resource */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+#define HB_TAG_sfnt HB_TAG ('s','f','n','t')
+
+struct ResourceTypeRecord
+{
+  unsigned int get_resource_count () const
+  { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }
+
+  bool is_sfnt () const { return tag == HB_TAG_sfnt; }
+
+  const ResourceRecord& get_resource_record (unsigned int i,
+                                            const void *type_base) const
+  { return (type_base+resourcesZ).as_array (get_resource_count ())[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                const void *type_base,
+                const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 resourcesZ.sanitize (c, type_base,
+                                      get_resource_count (),
+                                      data_base));
+  }
+
+  protected:
+  Tag          tag;            /* Resource type. */
+  HBUINT16     resCountM1;     /* Number of resources minus 1. */
+  NNOffsetTo<UnsizedArrayOf<ResourceRecord> >
+               resourcesZ;     /* Offset from beginning of resource type list
+                                * to reference item list for this type. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ResourceMap
+{
+  unsigned int get_face_count () const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      if (type.is_sfnt ())
+       return type.get_resource_count ();
+    }
+    return 0;
+  }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                   const void *data_base) const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      /* The check for idx < count is here because ResourceRecord is NOT null-safe.
+       * Because an offset of 0 there does NOT mean null. */
+      if (type.is_sfnt () && idx < type.get_resource_count ())
+       return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
+    }
+    return Null (OpenTypeFontFace);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 typeList.sanitize (c, this,
+                                    &(this+typeList),
+                                    data_base));
+  }
+
+  private:
+  unsigned int get_type_count () const { return (this+typeList).lenM1 + 1; }
+
+  const ResourceTypeRecord& get_type_record (unsigned int i) const
+  { return (this+typeList)[i]; }
+
+  protected:
+  HBUINT8      reserved0[16];  /* Reserved for copy of resource header */
+  HBUINT32     reserved1;      /* Reserved for handle to next resource map */
+  HBUINT16     resreved2;      /* Reserved for file reference number */
+  HBUINT16     attrs;          /* Resource fork attribute */
+  NNOffsetTo<ArrayOfM1<ResourceTypeRecord> >
+               typeList;       /* Offset from beginning of map to
+                                * resource type list */
+  Offset16     nameList;       /* Offset from beginning of map to
+                                * resource name list */
+  public:
+  DEFINE_SIZE_STATIC (28);
+};
+
+struct ResourceForkHeader
+{
+  unsigned int get_face_count () const
+  { return (this+map).get_face_count (); }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                   unsigned int *base_offset = nullptr) const
+  {
+    const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
+    if (base_offset)
+      *base_offset = (const char *) &face - (const char *) this;
+    return face;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 data.sanitize (c, this, dataLen) &&
+                 map.sanitize (c, this, &(this+data)));
+  }
+
+  protected:
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
+               data;           /* Offset from beginning of resource fork
+                                * to resource data */
+  LNNOffsetTo<ResourceMap >
+               map;            /* Offset from beginning of resource fork
+                                * to resource map */
+  HBUINT32     dataLen;        /* Length of resource data */
+  HBUINT32     mapLen;         /* Length of resource map */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+/*
+ * OpenType Font File
+ */
+
+struct OpenTypeFontFile
+{
+  enum {
+    CFFTag             = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
+    TrueTypeTag                = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
+    TTCTag             = HB_TAG ('t','t','c','f'), /* TrueType Collection */
+    DFontTag           = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
+    TrueTag            = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
+    Typ1Tag            = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
+  };
+
+  hb_tag_t get_tag () const { return u.tag; }
+
+  unsigned int get_face_count () const
+  {
+    switch (u.tag) {
+    case CFFTag:       /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:  return 1;
+    case TTCTag:       return u.ttcHeader.get_face_count ();
+    case DFontTag:     return u.rfHeader.get_face_count ();
+    default:           return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
+  {
+    if (base_offset)
+      *base_offset = 0;
+    switch (u.tag) {
+    /* Note: for non-collection SFNT data we ignore index.  This is because
+     * Apple dfont container is a container of SFNT's.  So each SFNT is a
+     * non-TTC, but the index is more than zero. */
+    case CFFTag:       /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:  return u.fontFace;
+    case TTCTag:       return u.ttcHeader.get_face (i);
+    case DFontTag:     return u.rfHeader.get_face (i, base_offset);
+    default:           return Null(OpenTypeFontFace);
+    }
+  }
+
+  template <typename item_t>
+  bool serialize_single (hb_serialize_context_t *c,
+                        hb_tag_t sfnt_tag,
+                        hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    assert (sfnt_tag != TTCTag);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    return_trace (u.fontFace.serialize (c, sfnt_tag, items));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
+    switch (u.tag) {
+    case CFFTag:       /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:  return_trace (u.fontFace.sanitize (c));
+    case TTCTag:       return_trace (u.ttcHeader.sanitize (c));
+    case DFontTag:     return_trace (u.rfHeader.sanitize (c));
+    default:           return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  Tag                  tag;            /* 4-byte identifier. */
+  OpenTypeFontFace     fontFace;
+  TTCHeader            ttcHeader;
+  ResourceForkHeader   rfHeader;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (4, tag);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_FILE_HH */
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
deleted file mode 100644 (file)
index 8180287..0000000
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 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
- */
-
-#ifndef HB_OPEN_TYPE_PRIVATE_HH
-#define HB_OPEN_TYPE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
-#include "hb-face-private.hh"
-
-
-namespace OT {
-
-
-
-/*
- * Casts
- */
-
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
-/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
- * location pointed to by P plus Ofs bytes. */
-template<typename Type>
-static inline const Type& StructAtOffset(const void *P, unsigned int offset)
-{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
-template<typename Type>
-static inline Type& StructAtOffset(void *P, unsigned int offset)
-{ return * reinterpret_cast<Type*> ((char *) P + offset); }
-
-/* StructAfter<T>(X) returns the struct T& that is placed after X.
- * Works with X of variable size also.  X must implement get_size() */
-template<typename Type, typename TObject>
-static inline const Type& StructAfter(const TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-template<typename Type, typename TObject>
-static inline Type& StructAfter(TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-
-
-
-/*
- * Size checking
- */
-
-/* Check _assertion in a method environment */
-#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
-  inline void _instance_assertion_on_line_##_line (void) const \
-  { \
-    static_assert ((_assertion), ""); \
-    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
-  }
-# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
-# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
-
-/* Check that _code compiles in a method environment */
-#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
-  inline void _compiles_assertion_on_line_##_line (void) const \
-  { _code; }
-# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
-# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
-
-
-#define DEFINE_SIZE_STATIC(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
-  static const unsigned int static_size = (size); \
-  static const unsigned int min_size = (size); \
-  inline unsigned int get_size (void) const { return (size); }
-
-#define DEFINE_SIZE_UNION(size, _member) \
-  DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_MIN(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY(size, array) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
-  static const unsigned int min_size = (size)
-
-
-
-/*
- * Dispatch
- */
-
-template <typename Context, typename Return, unsigned int MaxDebugDepth>
-struct hb_dispatch_context_t
-{
-  static const unsigned int max_debug_depth = MaxDebugDepth;
-  typedef Return return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
-  static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
-};
-
-
-/*
- * Sanitize
- */
-
-/* This limits sanitizing time on really broken fonts. */
-#ifndef HB_SANITIZE_MAX_EDITS
-#define HB_SANITIZE_MAX_EDITS 32
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_MIN
-#define HB_SANITIZE_MAX_OPS_MIN 16384
-#endif
-
-struct hb_sanitize_context_t :
-       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-{
-  inline hb_sanitize_context_t (void) :
-       debug_depth (0),
-       start (nullptr), end (nullptr),
-       writable (false), edit_count (0), max_ops (0),
-       blob (nullptr),
-       num_glyphs (0) {}
-
-  inline const char *get_name (void) { return "SANITIZE"; }
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format)
-  { return format->sanitize (this); }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
-  static return_t default_return_value (void) { return true; }
-  static return_t no_dispatch_return_value (void) { return false; }
-  bool stop_sublookup_iteration (const return_t r) const { return !r; }
-
-  inline void init (hb_blob_t *b)
-  {
-    this->blob = hb_blob_reference (b);
-    this->writable = false;
-  }
-
-  inline void start_processing (void)
-  {
-    this->start = hb_blob_get_data (this->blob, nullptr);
-    this->end = this->start + this->blob->length;
-    assert (this->start <= this->end); /* Must not overflow. */
-    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
-                        (unsigned) HB_SANITIZE_MAX_OPS_MIN);
-    this->edit_count = 0;
-    this->debug_depth = 0;
-
-    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
-                    "start [%p..%p] (%lu bytes)",
-                    this->start, this->end,
-                    (unsigned long) (this->end - this->start));
-  }
-
-  inline void end_processing (void)
-  {
-    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
-                    "end [%p..%p] %u edit requests",
-                    this->start, this->end, this->edit_count);
-
-    hb_blob_destroy (this->blob);
-    this->blob = nullptr;
-    this->start = this->end = nullptr;
-  }
-
-  inline bool check_range (const void *base, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool ok = this->max_ops-- > 0 &&
-             this->start <= p &&
-             p <= this->end &&
-             (unsigned int) (this->end - p) >= len;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       p, p + len, len,
-       this->start, this->end,
-       ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
-    unsigned int array_size = record_size * len;
-    bool ok = !overflows && this->check_range (base, array_size);
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
-       p, p + (record_size * len), record_size, len, (unsigned int) array_size,
-       this->start, this->end,
-       overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  template <typename Type>
-  inline bool check_struct (const Type *obj) const
-  {
-    return likely (this->check_range (obj, obj->min_size));
-  }
-
-  inline bool may_edit (const void *base, unsigned int len)
-  {
-    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
-      return false;
-
-    const char *p = (const char *) base;
-    this->edit_count++;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       this->edit_count,
-       p, p + len, len,
-       this->start, this->end,
-       this->writable ? "GRANTED" : "DENIED");
-
-    return this->writable;
-  }
-
-  template <typename Type, typename ValueType>
-  inline bool try_set (const Type *obj, const ValueType &v) {
-    if (this->may_edit (obj, obj->static_size)) {
-      const_cast<Type *> (obj)->set (v);
-      return true;
-    }
-    return false;
-  }
-
-  mutable unsigned int debug_depth;
-  const char *start, *end;
-  bool writable;
-  unsigned int edit_count;
-  mutable int max_ops;
-  hb_blob_t *blob;
-  unsigned int num_glyphs;
-};
-
-
-
-/* Template to sanitize an object. */
-template <typename Type>
-struct Sanitizer
-{
-  inline Sanitizer (void) {}
-
-  inline hb_blob_t *sanitize (hb_blob_t *blob) {
-    bool sane;
-
-    /* TODO is_sane() stuff */
-
-    c->init (blob);
-
-  retry:
-    DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
-
-    c->start_processing ();
-
-    if (unlikely (!c->start)) {
-      c->end_processing ();
-      return blob;
-    }
-
-    Type *t = CastP<Type> (const_cast<char *> (c->start));
-
-    sane = t->sanitize (c);
-    if (sane) {
-      if (c->edit_count) {
-       DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
-
-        /* sanitize again to ensure no toe-stepping */
-        c->edit_count = 0;
-       sane = t->sanitize (c);
-       if (c->edit_count) {
-         DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
-         sane = false;
-       }
-      }
-    } else {
-      unsigned int edit_count = c->edit_count;
-      if (edit_count && !c->writable) {
-        c->start = hb_blob_get_data_writable (blob, nullptr);
-       c->end = c->start + blob->length;
-
-       if (c->start) {
-         c->writable = true;
-         /* ok, we made it writable by relocating.  try again */
-         DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
-         goto retry;
-       }
-      }
-    }
-
-    c->end_processing ();
-
-    DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
-    if (sane)
-    {
-      blob->lock ();
-      return blob;
-    }
-    else
-    {
-      hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
-    }
-  }
-
-  inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
-
-  private:
-  hb_sanitize_context_t c[1];
-};
-
-
-
-/*
- * Serialize
- */
-
-
-struct hb_serialize_context_t
-{
-  inline hb_serialize_context_t (void *start_, unsigned int size)
-  {
-    this->start = (char *) start_;
-    this->end = this->start + size;
-
-    this->ran_out_of_room = false;
-    this->head = this->start;
-    this->debug_depth = 0;
-  }
-
-  template <typename Type>
-  inline Type *start_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
-                    "start [%p..%p] (%lu bytes)",
-                    this->start, this->end,
-                    (unsigned long) (this->end - this->start));
-
-    return start_embed<Type> ();
-  }
-
-  inline void end_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
-                    "end [%p..%p] serialized %d bytes; %s",
-                    this->start, this->end,
-                    (int) (this->head - this->start),
-                    this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
-
-  }
-
-  template <typename Type>
-  inline Type *copy (void)
-  {
-    assert (!this->ran_out_of_room);
-    unsigned int len = this->head - this->start;
-    void *p = malloc (len);
-    if (p)
-      memcpy (p, this->start, len);
-    return reinterpret_cast<Type *> (p);
-  }
-
-  template <typename Type>
-  inline Type *allocate_size (unsigned int size)
-  {
-    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
-      this->ran_out_of_room = true;
-      return nullptr;
-    }
-    memset (this->head, 0, size);
-    char *ret = this->head;
-    this->head += size;
-    return reinterpret_cast<Type *> (ret);
-  }
-
-  template <typename Type>
-  inline Type *allocate_min (void)
-  {
-    return this->allocate_size<Type> (Type::min_size);
-  }
-
-  template <typename Type>
-  inline Type *start_embed (void)
-  {
-    Type *ret = reinterpret_cast<Type *> (this->head);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *embed (const Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    Type *ret = this->allocate_size<Type> (size);
-    if (unlikely (!ret)) return nullptr;
-    memcpy (ret, obj, size);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *extend_min (Type &obj)
-  {
-    unsigned int size = obj.min_size;
-    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  template <typename Type>
-  inline Type *extend (Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  inline void truncate (void *new_head)
-  {
-    assert (this->start < new_head && new_head <= this->head);
-    this->head = (char *) new_head;
-  }
-
-  unsigned int debug_depth;
-  char *start, *end, *head;
-  bool ran_out_of_room;
-};
-
-template <typename Type>
-struct Supplier
-{
-  inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
-  {
-    head = array;
-    len = len_;
-    stride = stride_;
-  }
-  inline const Type operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Type ();
-    return * (const Type *) (const void *) ((const char *) head + stride * i);
-  }
-
-  inline Supplier<Type> & operator += (unsigned int count)
-  {
-    if (unlikely (count > len))
-      count = len;
-    len -= count;
-    head = (const Type *) (const void *) ((const char *) head + stride * count);
-    return *this;
-  }
-
-  private:
-  inline Supplier (const Supplier<Type> &); /* Disallow copy */
-  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
-
-  unsigned int len;
-  unsigned int stride;
-  const Type *head;
-};
-
-
-/*
- *
- * The OpenType Font File: Data Types
- */
-
-
-/* "The following data types are used in the OpenType font file.
- *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
-
-/*
- * Int types
- */
-
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
-  public:
-  inline void set (Type V)
-  {
-    v = V;
-  }
-  inline operator Type (void) const
-  {
-    return v;
-  }
-  private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >>  8) & 0xFF;
-    v[1] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] <<  8)
-         + (v[1]      );
-  }
-  private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[2] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 16)
-         + (v[1] <<  8)
-         + (v[2]      );
-  }
-  private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 24) & 0xFF;
-    v[1] = (V >> 16) & 0xFF;
-    v[2] = (V >>  8) & 0xFF;
-    v[3] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 24)
-         + (v[1] << 16)
-         + (v[2] <<  8)
-         + (v[3]      );
-  }
-  private: uint8_t v[4];
-};
-
-/* Integer types in big-endian order and no alignment requirement */
-template <typename Type, unsigned int Size>
-struct IntType
-{
-  inline void set (Type i) { v.set (i); }
-  inline operator Type(void) const { return v; }
-  inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-  inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
-  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-  template <typename Type2>
-  inline int cmp (Type2 a) const
-  {
-    Type b = v;
-    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-      return (int) a - (int) b;
-    else
-      return a < b ? -1 : a == b ? 0 : +1;
-  }
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  BEInt<Type, Size> v;
-  public:
-  DEFINE_SIZE_STATIC (Size);
-};
-
-typedef IntType<uint8_t,  1> HBUINT8;  /* 8-bit unsigned integer. */
-typedef IntType<int8_t,   1> HBINT8;   /* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> HBINT16;  /* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> HBINT32;  /* 32-bit signed integer. */
-typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
-
-/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
-typedef HBINT16 FWORD;
-
-/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
-typedef HBUINT16 UFWORD;
-
-/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : HBINT16
-{
-  // 16384 means 1<<14
-  inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
-  inline void set_float (float f) { v.set (round (f * 16384.f)); }
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-/* 32-bit signed fixed-point number (16.16). */
-struct Fixed : HBINT32
-{
-  // 65536 means 1<<16
-  inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
-  inline void set_float (float f) { v.set (round (f * 65536.f)); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* Date represented in number of seconds since 12:00 midnight, January 1,
- * 1904. The value is represented as a signed 64-bit integer. */
-struct LONGDATETIME
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  HBINT32 major;
-  HBUINT32 minor;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-/* Array of four uint8s (length = 32 bits) used to identify a script, language
- * system, feature, or baseline */
-struct Tag : HBUINT32
-{
-  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
-  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-DEFINE_NULL_DATA (OT, Tag, "    ");
-
-/* Glyph index number, same as uint16 (length = 16 bits) */
-typedef HBUINT16 GlyphID;
-
-/* Name-table index, same as uint16 (length = 16 bits) */
-typedef HBUINT16 NameID;
-
-/* Script/language-system/feature index */
-struct Index : HBUINT16 {
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
-};
-DEFINE_NULL_DATA (OT, Index, "\xff\xff");
-
-/* Offset, Null offset = 0 */
-template <typename Type>
-struct Offset : Type
-{
-  inline bool is_null (void) const { return 0 == *this; }
-
-  inline void *serialize (hb_serialize_context_t *c, const void *base)
-  {
-    void *t = c->start_embed<void> ();
-    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-    return t;
-  }
-
-  public:
-  DEFINE_SIZE_STATIC (sizeof(Type));
-};
-
-typedef Offset<HBUINT16> Offset16;
-typedef Offset<HBUINT32> Offset32;
-
-
-/* CheckSum */
-struct CheckSum : HBUINT32
-{
-  /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
-  {
-    uint32_t Sum = 0L;
-    assert (0 == (Length & 3));
-    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
-
-    while (Table < EndPtr)
-      Sum += *Table++;
-    return Sum;
-  }
-
-  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
-  inline void set_for_data (const void *data, unsigned int length)
-  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-/*
- * Version Numbers
- */
-
-template <typename FixedType=HBUINT16>
-struct FixedVersion
-{
-  inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  FixedType major;
-  FixedType minor;
-  public:
-  DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
-};
-
-
-
-/*
- * Template subclasses of Offset that do the dereferencing.
- * Use: (base+offset)
- */
-
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
-{
-  inline const Type& operator () (const void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Null(Type);
-    return StructAtOffset<const Type> (base, offset);
-  }
-  inline Type& operator () (void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Crap(Type);
-    return StructAtOffset<Type> (base, offset);
-  }
-
-  inline Type& serialize (hb_serialize_context_t *c, const void *base)
-  {
-    return * (Type *) Offset<OffsetType>::serialize (c, base);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c)) || neuter (c));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
-  }
-
-  /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) const {
-    return c->try_set (this, 0);
-  }
-  DEFINE_SIZE_STATIC (sizeof(OffsetType));
-};
-template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-
-
-/*
- * Array Types
- */
-
-
-/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
-template <typename Type>
-struct UnsizedArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
-  inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
-  }
-
-  public:
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (0, arrayZ);
-};
-
-/* Unsized array of offset's */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Unsized array of offsets relative to the beginning of the array itself. */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
-  }
-};
-
-
-/* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
-struct ArrayOf
-{
-  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
-  {
-    unsigned int count = len;
-    if (unlikely (start_offset > count))
-      count = 0;
-    else
-      count -= start_offset;
-    count = MIN (count, *pcount);
-    *pcount = count;
-    return arrayZ + start_offset;
-  }
-
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Null(Type);
-    return arrayZ[i];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len)) return Crap(Type);
-    return arrayZ[i];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + len * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<Type> &items,
-                        unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return_trace (false);
-    for (unsigned int i = 0; i < items_len; i++)
-      arrayZ[i] = items[i];
-    items += items_len;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  template <typename SearchType>
-  inline int lsearch (const SearchType &x) const
-  {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!this->arrayZ[i].cmp (x))
-        return i;
-    return -1;
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
-
-/* Array of Offset's */
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= this->len)) return Null(Type);
-    return this+this->arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= this->len)) return Crap(Type);
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
-  }
-};
-
-
-/* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
-struct HeadlessArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len || !i)) return Null(Type);
-    return arrayZ[i-1];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len || !i)) return Crap(Type);
-    return arrayZ[i-1];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<Type> &items,
-                        unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return_trace (true);
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items_len - 1; i++)
-      arrayZ[i] = items[i];
-    items += items_len - 1;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) &&
-                 (!len || c->check_array (arrayZ, Type::static_size, len - 1)));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-
-
-/*
- * An array with sorted elements.  Supports binary searching.
- */
-template <typename Type, typename LenType=HBUINT16>
-struct SortedArrayOf : ArrayOf<Type, LenType>
-{
-  template <typename SearchType>
-  inline int bsearch (const SearchType &x) const
-  {
-    /* Hand-coded bsearch here since this is in the hot inner loop. */
-    const Type *arr = this->arrayZ;
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = arr[mid].cmp (x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-        return mid;
-    }
-    return -1;
-  }
-};
-
-/*
- * Binary-search arrays
- */
-
-struct BinSearchHeader
-{
-  inline operator uint32_t (void) const { return len; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void set (unsigned int v)
-  {
-    len.set (v);
-    assert (len == v);
-    entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1);
-    searchRange.set (16 * (1u << entrySelector));
-    rangeShift.set (v * 16 > searchRange
-                   ? 16 * v - searchRange
-                   : 0);
-  }
-
-  protected:
-  HBUINT16     len;
-  HBUINT16     searchRange;
-  HBUINT16     entrySelector;
-  HBUINT16     rangeShift;
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename Type>
-struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
-
-
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    if (instance && instance != &Null(T))
-    {
-      instance->fini();
-      free (instance);
-    }
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      p = (T *) calloc (1, sizeof (T));
-      if (unlikely (!p))
-        p = const_cast<T *> (&Null(T));
-      else
-       p->init (face);
-      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
-      {
-       if (p != &Null(T))
-         p->fini ();
-       goto retry;
-      }
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get ();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_table_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    blob = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (blob);
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
-    if (unlikely (!blob_))
-    {
-      blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
-      if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
-      {
-       hb_blob_destroy (blob_);
-       goto retry;
-      }
-      blob = blob_;
-    }
-    return blob_->as<T> ();
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get();
-  }
-
-  private:
-  hb_face_t *face;
-  mutable hb_blob_t *blob;
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_TYPE_PRIVATE_HH */
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
new file mode 100644 (file)
index 0000000..6abb898
--- /dev/null
@@ -0,0 +1,1008 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 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
+ */
+
+#ifndef HB_OPEN_TYPE_HH
+#define HB_OPEN_TYPE_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+#include "hb-face.hh"
+#include "hb-machinery.hh"
+#include "hb-subset.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File: Data Types
+ */
+
+
+/* "The following data types are used in the OpenType font file.
+ *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
+
+/*
+ * Int types
+ */
+
+template <bool is_signed> struct hb_signedness_int;
+template <> struct hb_signedness_int<false> { typedef unsigned int value; };
+template <> struct hb_signedness_int<true>  { typedef   signed int value; };
+
+/* Integer types in big-endian order and no alignment requirement */
+template <typename Type, unsigned int Size>
+struct IntType
+{
+  typedef Type type;
+  typedef typename hb_signedness_int<hb_is_signed<Type>::value>::value wide_type;
+
+  void set (wide_type i) { v.set (i); }
+  operator wide_type () const { return v; }
+  bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
+  bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
+  static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
+  template <typename Type2>
+  int cmp (Type2 a) const
+  {
+    Type b = v;
+    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
+      return (int) a - (int) b;
+    else
+      return a < b ? -1 : a == b ? 0 : +1;
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  BEInt<Type, Size> v;
+  public:
+  DEFINE_SIZE_STATIC (Size);
+};
+
+typedef IntType<uint8_t,  1> HBUINT8;  /* 8-bit unsigned integer. */
+typedef IntType<int8_t,   1> HBINT8;   /* 8-bit signed integer. */
+typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */
+typedef IntType<int16_t,  2> HBINT16;  /* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */
+typedef IntType<int32_t,  4> HBINT32;  /* 32-bit signed integer. */
+/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
+ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
+typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
+
+/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
+typedef HBINT16 FWORD;
+
+/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
+typedef HBINT32 FWORD32;
+
+/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
+typedef HBUINT16 UFWORD;
+
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+struct F2DOT14 : HBINT16
+{
+  // 16384 means 1<<14
+  float to_float () const  { return ((int32_t) v) / 16384.f; }
+  void set_float (float f) { v.set (round (f * 16384.f)); }
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+/* 32-bit signed fixed-point number (16.16). */
+struct Fixed : HBINT32
+{
+  // 65536 means 1<<16
+  float to_float () const  { return ((int32_t) v) / 65536.f; }
+  void set_float (float f) { v.set (round (f * 65536.f)); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Date represented in number of seconds since 12:00 midnight, January 1,
+ * 1904. The value is represented as a signed 64-bit integer. */
+struct LONGDATETIME
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  HBINT32 major;
+  HBUINT32 minor;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+/* Array of four uint8s (length = 32 bits) used to identify a script, language
+ * system, feature, or baseline */
+struct Tag : HBUINT32
+{
+  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
+  operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
+  operator char* ()             { return reinterpret_cast<char *> (&this->v); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Glyph index number, same as uint16 (length = 16 bits) */
+typedef HBUINT16 GlyphID;
+
+/* Script/language-system/feature index */
+struct Index : HBUINT16 {
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu;
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
+
+typedef Index NameID;
+
+/* Offset, Null offset = 0 */
+template <typename Type, bool has_null=true>
+struct Offset : Type
+{
+  typedef Type type;
+
+  bool is_null () const { return has_null && 0 == *this; }
+
+  void *serialize (hb_serialize_context_t *c, const void *base)
+  {
+    void *t = c->start_embed<void> ();
+    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
+    return t;
+  }
+
+  public:
+  DEFINE_SIZE_STATIC (sizeof (Type));
+};
+
+typedef Offset<HBUINT16> Offset16;
+typedef Offset<HBUINT32> Offset32;
+
+
+/* CheckSum */
+struct CheckSum : HBUINT32
+{
+  /* This is reference implementation from the spec. */
+  static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
+  {
+    uint32_t Sum = 0L;
+    assert (0 == (Length & 3));
+    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
+
+    while (Table < EndPtr)
+      Sum += *Table++;
+    return Sum;
+  }
+
+  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
+  void set_for_data (const void *data, unsigned int length)
+  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+
+/*
+ * Version Numbers
+ */
+
+template <typename FixedType=HBUINT16>
+struct FixedVersion
+{
+  uint32_t to_int () const { return (major << (sizeof (FixedType) * 8)) + minor; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  FixedType major;
+  FixedType minor;
+  public:
+  DEFINE_SIZE_STATIC (2 * sizeof (FixedType));
+};
+
+
+/*
+ * Template subclasses of Offset that do the dereferencing.
+ * Use: (base+offset)
+ */
+
+template <typename Type, bool has_null>
+struct _hb_has_null
+{
+  static const Type *get_null () { return nullptr; }
+  static Type *get_crap ()       { return nullptr; }
+};
+template <typename Type>
+struct _hb_has_null<Type, true>
+{
+  static const Type *get_null () { return &Null(Type); }
+  static Type *get_crap ()       { return &Crap(Type); }
+};
+
+template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+struct OffsetTo : Offset<OffsetType, has_null>
+{
+  const Type& operator () (const void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
+    return StructAtOffset<const Type> (base, *this);
+  }
+  Type& operator () (void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
+    return StructAtOffset<Type> (base, *this);
+  }
+
+  Type& serialize (hb_serialize_context_t *c, const void *base)
+  {
+    return * (Type *) Offset<OffsetType>::serialize (c, base);
+  }
+
+  template <typename T>
+  void serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
+  {
+    if (&src == &Null (T))
+    {
+      this->set (0);
+      return;
+    }
+    serialize (c->serializer, base);
+    if (!src.subset (c))
+      this->set (0);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (this->is_null ())) return_trace (true);
+    if (unlikely (!c->check_range (base, *this))) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                 (this->is_null () ||
+                  StructAtOffset<Type> (base, *this).sanitize (c) ||
+                  neuter (c)));
+  }
+  template <typename T1>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                 (this->is_null () ||
+                  StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
+                  neuter (c)));
+  }
+  template <typename T1, typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                 (this->is_null () ||
+                  StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
+                  neuter (c)));
+  }
+  template <typename T1, typename T2, typename T3>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                 (this->is_null () ||
+                  StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
+                  neuter (c)));
+  }
+
+  /* Set the offset to Null */
+  bool neuter (hb_sanitize_context_t *c) const
+  {
+    if (!has_null) return false;
+    return c->try_set (this, 0);
+  }
+  DEFINE_SIZE_STATIC (sizeof (OffsetType));
+};
+/* Partial specializations. */
+template <typename Type,                               bool has_null=true> struct   LOffsetTo : OffsetTo<Type, HBUINT32,   has_null> {};
+template <typename Type, typename OffsetType=HBUINT16                    > struct  NNOffsetTo : OffsetTo<Type, OffsetType, false> {};
+template <typename Type                                                  > struct LNNOffsetTo : OffsetTo<Type, HBUINT32,   false> {};
+
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+
+
+/*
+ * Array Types
+ */
+
+template <typename Type>
+struct UnsizedArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+    return *p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+    return *p;
+  }
+
+  unsigned int get_size (unsigned int len) const
+  { return len * Type::static_size; }
+
+  template <typename T> operator T * () { return arrayZ; }
+  template <typename T> operator const T * () const { return arrayZ; }
+  hb_array_t<Type> as_array (unsigned int len)
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array (unsigned int len) const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &lsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).lsearch (x, &not_found); }
+
+  void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array (len).qsort (start, end); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+       return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+       return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_array (arrayZ, count));
+  }
+
+  public:
+  Type         arrayZ[VAR];
+  public:
+  DEFINE_SIZE_UNBOUNDED (0);
+};
+
+/* Unsized array of offset's */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
+
+/* Unsized array of offsets relative to the beginning of the array itself. */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+    return this+*p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+    return this+*p;
+  }
+
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
+  }
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type>
+struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
+{
+  hb_sorted_array_t<Type> as_array (unsigned int len)
+  { return hb_sorted_array (this->arrayZ, len); }
+  hb_sorted_array_t<const Type> as_array (unsigned int len) const
+  { return hb_sorted_array (this->arrayZ, len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &bsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
+                    hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                    unsigned int to_store = (unsigned int) -1) const
+  { return as_array (len).bfind (x, i, not_found, to_store); }
+};
+
+
+/* An array with a number of elements. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Crap (Type);
+    return arrayZ[i];
+  }
+
+  unsigned int get_size () const
+  { return len.static_size + len * Type::static_size; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> (void)             { return as_array (); }
+  operator hb_array_t<const Type> (void) const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    len.set (items_len); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!serialize (c, items.length))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      hb_assign (arrayZ[i], items[i]);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+       return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+       return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  Type &lsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().lsearch (x, &not_found); }
+
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
+  }
+
+  public:
+  LenType      len;
+  Type         arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
+typedef ArrayOf<HBUINT8, HBUINT8> PString;
+
+/* Array of Offset's */
+template <typename Type>
+struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {};
+template <typename Type>
+struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {};
+template <typename Type>
+struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {};
+
+/* Array of offsets relative to the beginning of the array itself. */
+template <typename Type>
+struct OffsetListOf : OffsetArrayOf<Type>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Null (Type);
+    return this+this->arrayZ[i];
+  }
+  const Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Crap (Type);
+    return this+this->arrayZ[i];
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct OffsetListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->arrayZ[i].serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
+  }
+};
+
+/* An array starting at second element. */
+template <typename Type, typename LenType=HBUINT16>
+struct HeadlessArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Null (Type);
+    return arrayZ[i-1];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+    return arrayZ[i-1];
+  }
+  unsigned int get_size () const
+  { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const Type> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      arrayZ[i] = items[i];
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenP1.sanitize (c) &&
+                 (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
+  }
+
+  public:
+  LenType      lenP1;
+  Type         arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array storing length-1. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOfM1
+{
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Crap (Type);
+    return arrayZ[i];
+  }
+  unsigned int get_size () const
+  { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
+
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = lenM1 + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+       return_trace (false);
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenM1.sanitize (c) &&
+                 (c->check_array (arrayZ, lenM1 + 1)));
+  }
+
+  public:
+  LenType      lenM1;
+  Type         arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type, typename LenType=HBUINT16>
+struct SortedArrayOf : ArrayOf<Type, LenType>
+{
+  hb_sorted_array_t<Type> as_array ()
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  hb_sorted_array_t<const Type> as_array () const
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  template <typename T>
+  Type &bsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().bsearch (x, &not_found); }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                    hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                    unsigned int to_store = (unsigned int) -1) const
+  { return as_array ().bfind (x, i, not_found, to_store); }
+};
+
+/*
+ * Binary-search arrays
+ */
+
+template <typename LenType=HBUINT16>
+struct BinSearchHeader
+{
+  operator uint32_t () const { return len; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void set (unsigned int v)
+  {
+    len.set (v);
+    assert (len == v);
+    entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1);
+    searchRange.set (16 * (1u << entrySelector));
+    rangeShift.set (v * 16 > searchRange
+                   ? 16 * v - searchRange
+                   : 0);
+  }
+
+  protected:
+  LenType      len;
+  LenType      searchRange;
+  LenType      entrySelector;
+  LenType      rangeShift;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename Type, typename LenType=HBUINT16>
+struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
+
+
+struct VarSizedBinSearchHeader
+{
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16     unitSize;       /* Size of a lookup unit for this search in bytes. */
+  HBUINT16     nUnits;         /* Number of units of the preceding size to be searched. */
+  HBUINT16     searchRange;    /* The value of unitSize times the largest power of 2
+                                * that is less than or equal to the value of nUnits. */
+  HBUINT16     entrySelector;  /* The log base 2 of the largest power of 2 less than
+                                * or equal to the value of nUnits. */
+  HBUINT16     rangeShift;     /* The value of unitSize times the difference of the
+                                * value of nUnits minus the largest power of 2 less
+                                * than or equal to the value of nUnits. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+template <typename Type>
+struct VarSizedBinSearchArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
+
+  bool last_is_terminator () const
+  {
+    if (unlikely (!header.nUnits)) return false;
+
+    /* Gah.
+     *
+     * "The number of termination values that need to be included is table-specific.
+     * The value that indicates binary search termination is 0xFFFF." */
+    const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
+    unsigned int count = Type::TerminationWordCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (words[i] != 0xFFFFu)
+        return false;
+    return true;
+  }
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Null (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Crap (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  unsigned int get_length () const
+  { return header.nUnits - last_is_terminator (); }
+  unsigned int get_size () const
+  { return header.static_size + header.nUnits * header.unitSize; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base)))
+       return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
+       return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  const Type *bsearch (const T &key) const
+  {
+    unsigned int size = header.unitSize;
+    int min = 0, max = (int) get_length () - 1;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
+      int c = p->cmp (key);
+      if (c < 0) max = mid - 1;
+      else if (c > 0) min = mid + 1;
+      else return p;
+    }
+    return nullptr;
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (header.sanitize (c) &&
+                 Type::static_size <= header.unitSize &&
+                 c->check_range (bytesZ.arrayZ,
+                                 header.nUnits,
+                                 header.unitSize));
+  }
+
+  protected:
+  VarSizedBinSearchHeader      header;
+  UnsizedArrayOf<HBUINT8>      bytesZ;
+  public:
+  DEFINE_SIZE_ARRAY (10, bytesZ);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_TYPE_HH */
diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh
new file mode 100644 (file)
index 0000000..c645953
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_OT_CFF_COMMON_HH
+#define HB_OT_CFF_COMMON_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-cff-interp-dict-common.hh"
+#include "hb-subset-plan.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+#define CFF_UNDEF_CODE  0xFFFFFFFF
+
+/* utility macro */
+template<typename Type>
+static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
+{ return offset? (* reinterpret_cast<const Type*> ((const char *) P + offset)): Null(Type); }
+
+inline unsigned int calcOffSize(unsigned int dataSize)
+{
+  unsigned int size = 1;
+  unsigned int offset = dataSize + 1;
+  while ((offset & ~0xFF) != 0)
+  {
+    size++;
+    offset >>= 8;
+  }
+  /* format does not support size > 4; caller should handle it as an error */
+  return size;
+}
+
+struct code_pair_t
+{
+  hb_codepoint_t  code;
+  hb_codepoint_t  glyph;
+};
+
+typedef hb_vector_t<unsigned char> str_buff_t;
+struct str_buff_vec_t : hb_vector_t<str_buff_t>
+{
+  void fini () { SUPER::fini_deep (); }
+
+  unsigned int total_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < length; i++)
+      size += (*this)[i].length;
+    return size;
+  }
+
+  private:
+  typedef hb_vector_t<str_buff_t> SUPER;
+};
+
+/* CFF INDEX */
+template <typename COUNT>
+struct CFFIndex
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
+                         (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
+                          c->check_array (offsets, offSize, count + 1) &&
+                          c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
+  }
+
+  static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
+  { return offSize * (count + 1); }
+
+  unsigned int offset_array_size () const
+  { return calculate_offset_array_size (offSize, count); }
+
+  static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
+  {
+    if (count == 0)
+      return COUNT::static_size;
+    else
+      return min_size + calculate_offset_array_size (offSize, count) + dataSize;
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    CFFIndex *dest = c->allocate_size<CFFIndex> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int offSize_,
+                 const byte_str_array_t &byteArray)
+  {
+    TRACE_SERIALIZE (this);
+    if (byteArray.length == 0)
+    {
+      COUNT *dest = c->allocate_min<COUNT> ();
+      if (unlikely (dest == nullptr)) return_trace (false);
+      dest->set (0);
+    }
+    else
+    {
+      /* serialize CFFIndex header */
+      if (unlikely (!c->extend_min (*this))) return_trace (false);
+      this->count.set (byteArray.length);
+      this->offSize.set (offSize_);
+      if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+       return_trace (false);
+
+      /* serialize indices */
+      unsigned int  offset = 1;
+      unsigned int  i = 0;
+      for (; i < byteArray.length; i++)
+      {
+       set_offset_at (i, offset);
+       offset += byteArray[i].get_size ();
+      }
+      set_offset_at (i, offset);
+
+      /* serialize data */
+      for (unsigned int i = 0; i < byteArray.length; i++)
+      {
+       const byte_str_t &bs = byteArray[i];
+       unsigned char  *dest = c->allocate_size<unsigned char> (bs.length);
+       if (unlikely (dest == nullptr))
+         return_trace (false);
+       memcpy (dest, &bs[0], bs.length);
+      }
+    }
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int offSize_,
+                 const str_buff_vec_t &buffArray)
+  {
+    byte_str_array_t  byteArray;
+    byteArray.init ();
+    byteArray.resize (buffArray.length);
+    for (unsigned int i = 0; i < byteArray.length; i++)
+    {
+      byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length);
+    }
+    bool result = this->serialize (c, offSize_, byteArray);
+    byteArray.fini ();
+    return result;
+  }
+
+  void set_offset_at (unsigned int index, unsigned int offset)
+  {
+    HBUINT8 *p = offsets + offSize * index + offSize;
+    unsigned int size = offSize;
+    for (; size; size--)
+    {
+      --p;
+      p->set (offset & 0xFF);
+      offset >>= 8;
+    }
+  }
+
+  unsigned int offset_at (unsigned int index) const
+  {
+    assert (index <= count);
+    const HBUINT8 *p = offsets + offSize * index;
+    unsigned int size = offSize;
+    unsigned int offset = 0;
+    for (; size; size--)
+      offset = (offset << 8) + *p++;
+    return offset;
+  }
+
+  unsigned int length_at (unsigned int index) const
+  {
+       if (likely ((offset_at (index + 1) >= offset_at (index)) &&
+                   (offset_at (index + 1) <= offset_at (count))))
+         return offset_at (index + 1) - offset_at (index);
+       else
+         return 0;
+  }
+
+  const unsigned char *data_base () const
+  { return (const unsigned char *)this + min_size + offset_array_size (); }
+
+  unsigned int data_size () const { return HBINT8::static_size; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < count))
+      return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+    else
+      return Null(byte_str_t);
+  }
+
+  unsigned int get_size () const
+  {
+    if (this != &Null(CFFIndex))
+    {
+      if (count > 0)
+       return min_size + offset_array_size () + (offset_at (count) - 1);
+      else
+       return count.static_size;  /* empty CFFIndex contains count only */
+    }
+    else
+      return 0;
+  }
+
+  protected:
+  unsigned int max_offset () const
+  {
+    unsigned int max = 0;
+    for (unsigned int i = 0; i < count + 1u; i++)
+    {
+      unsigned int off = offset_at (i);
+      if (off > max) max = off;
+    }
+    return max;
+  }
+
+  public:
+  COUNT     count;     /* Number of object data. Note there are (count+1) offsets */
+  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
+  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
+  /* HBUINT8 data[VAR];      Object data */
+  public:
+  DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+};
+
+template <typename COUNT, typename TYPE>
+struct CFFIndexOf : CFFIndex<COUNT>
+{
+  const byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < CFFIndex<COUNT>::count))
+      return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
+    return Null(byte_str_t);
+  }
+
+  template <typename DATA, typename PARAM1, typename PARAM2>
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int offSize_,
+                 const DATA *dataArray,
+                 unsigned int dataArrayLen,
+                 const hb_vector_t<unsigned int> &dataSizeArray,
+                 const PARAM1 &param1,
+                 const PARAM2 &param2)
+  {
+    TRACE_SERIALIZE (this);
+    /* serialize CFFIndex header */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (dataArrayLen);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+      return_trace (false);
+
+    /* serialize indices */
+    unsigned int  offset = 1;
+    unsigned int  i = 0;
+    for (; i < dataArrayLen; i++)
+    {
+      CFFIndex<COUNT>::set_offset_at (i, offset);
+      offset += dataSizeArray[i];
+    }
+    CFFIndex<COUNT>::set_offset_at (i, offset);
+
+    /* serialize data */
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      TYPE  *dest = c->start_embed<TYPE> ();
+      if (unlikely (dest == nullptr ||
+                   !dest->serialize (c, dataArray[i], param1, param2)))
+       return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DATA, typename PARAM>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                const DATA *dataArray,
+                                                unsigned int dataArrayLen,
+                                                hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
+                                                const PARAM &param)
+  {
+    /* determine offset size */
+    unsigned int  totalDataSize = 0;
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
+      dataSizeArray[i] = dataSize;
+      totalDataSize += dataSize;
+    }
+    offSize_ = calcOffSize (totalDataSize);
+
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
+  }
+};
+
+/* Top Dict, Font Dict, Private Dict */
+struct Dict : UnsizedByteStr
+{
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  bool serialize (hb_serialize_context_t *c,
+                 const DICTVAL &dictval,
+                 OP_SERIALIZER& opszr,
+                 PARAM& param)
+  {
+    TRACE_SERIALIZE (this);
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+    {
+      if (unlikely (!opszr.serialize (c, dictval[i], param)))
+       return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                OP_SERIALIZER& opszr,
+                                                PARAM& param)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i], param);
+    return size;
+  }
+
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                OP_SERIALIZER& opszr)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i]);
+    return size;
+  }
+
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, int value, op_code_t intOp)
+  {
+    // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
+    if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
+      return false;
+
+    TRACE_SERIALIZE (this);
+    /* serialize the opcode */
+    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+    if (unlikely (p == nullptr)) return_trace (false);
+    if (Is_OpCode_ESC (op))
+    {
+      p->set (OpCode_escape);
+      op = Unmake_OpCode_ESC (op);
+      p++;
+    }
+    p->set (op);
+    return_trace (true);
+  }
+
+  static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
+
+  static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
+
+  static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint4_op (c, op, value);
+  }
+
+  static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint2_op (c, op, value);
+  }
+};
+
+struct TopDict : Dict {};
+struct FontDict : Dict {};
+struct PrivateDict : Dict {};
+
+struct table_info_t
+{
+  void init () { offSize = offset = size = 0; }
+
+  unsigned int    offset;
+  unsigned int    size;
+  unsigned int    offSize;
+};
+
+/* used to remap font index or SID from fullset to subset.
+ * set to CFF_UNDEF_CODE if excluded from subset */
+struct remap_t : hb_vector_t<hb_codepoint_t>
+{
+  void init () { SUPER::init (); }
+
+  void fini () { SUPER::fini (); }
+
+  bool reset (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i] = CFF_UNDEF_CODE;
+    count = 0;
+    return true;
+  }
+
+  bool identity (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    unsigned int i;
+    for (i = 0; i < length; i++)
+      (*this)[i] = i;
+    count = i;
+    return true;
+  }
+
+  bool excludes (hb_codepoint_t id) const
+  { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); }
+
+  bool includes (hb_codepoint_t id) const
+  { return !excludes (id); }
+
+  unsigned int add (unsigned int i)
+  {
+    if ((*this)[i] == CFF_UNDEF_CODE)
+      (*this)[i] = count++;
+    return (*this)[i];
+  }
+
+  hb_codepoint_t get_count () const { return count; }
+
+  protected:
+  hb_codepoint_t  count;
+
+  private:
+  typedef hb_vector_t<hb_codepoint_t> SUPER;
+};
+
+template <typename COUNT>
+struct FDArray : CFFIndexOf<COUNT, FontDict>
+{
+  /* used by CFF1 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int offSize_,
+                 const hb_vector_t<DICTVAL> &fontDicts,
+                 OP_SERIALIZER& opszr)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fontDicts.length);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int fid = 0;
+    for (; fid < fontDicts.length; fid++)
+    {
+      CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+      offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
+    }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+    {
+      FontDict *dict = c->start_embed<FontDict> ();
+      if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
+       return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* used by CFF2 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int offSize_,
+                 const hb_vector_t<DICTVAL> &fontDicts,
+                 unsigned int fdCount,
+                 const remap_t &fdmap,
+                 OP_SERIALIZER& opszr,
+                 const hb_vector_t<table_info_t> &privateInfos)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fdCount);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int  fid = 0;
+    for (unsigned i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+       CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
+       offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+      }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+       FontDict *dict = c->start_embed<FontDict> ();
+       if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
+         return_trace (false);
+      }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename OP_SERIALIZER, typename DICTVAL>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                const hb_vector_t<DICTVAL> &fontDicts,
+                                                unsigned int fdCount,
+                                                const remap_t &fdmap,
+                                                OP_SERIALIZER& opszr)
+  {
+    unsigned int dictsSize = 0;
+    for (unsigned int i = 0; i < fontDicts.len; i++)
+      if (fdmap.includes (i))
+       dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+
+    offSize_ = calcOffSize (dictsSize);
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
+  }
+};
+
+/* FDSelect */
+struct FDSelect0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this))))
+      return_trace (false);
+    for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
+      if (unlikely (!fds[i].sanitize (c)))
+       return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    return (hb_codepoint_t)fds[glyph];
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  { return HBUINT8::static_size * num_glyphs; }
+
+  HBUINT8     fds[VAR];
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4_Range {
+  bool sanitize (hb_sanitize_context_t *c, const void */*nullptr*/, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (first < c->get_num_glyphs () && (fd < fdcount));
+  }
+
+  GID_TYPE    first;
+  FD_TYPE     fd;
+
+  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4 {
+  unsigned int get_size () const
+  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
+                 (nRanges () == 0) || ranges[0].first != 0))
+      return_trace (false);
+
+    for (unsigned int i = 1; i < nRanges (); i++)
+    {
+      if (unlikely (ranges[i - 1].first >= ranges[i].first))
+         return_trace (false);
+    }
+
+    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
+      return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    for (i = 1; i < nRanges (); i++)
+      if (glyph < ranges[i].first)
+       break;
+
+    return (hb_codepoint_t)ranges[i - 1].fd;
+  }
+
+  GID_TYPE &nRanges () { return ranges.len; }
+  GID_TYPE nRanges () const { return ranges.len; }
+  GID_TYPE &sentinel ()  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+  const GID_TYPE &sentinel () const  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+
+  ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges;
+  /* GID_TYPE sentinel */
+
+  DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
+};
+
+typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
+typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
+
+struct FDSelect {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
+                         (format == 0)?
+                         u.format0.sanitize (c, fdcount):
+                         u.format3.sanitize (c, fdcount)));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    FDSelect *dest = c->allocate_size<FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else
+      size += u.format3.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else
+      return u.format3.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename COUNT>
+struct Subrs : CFFIndex<COUNT>
+{
+  typedef COUNT count_type;
+  typedef CFFIndex<COUNT> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_OT_CFF_COMMON_HH */
diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc
new file mode 100644 (file)
index 0000000..8773c05
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff1-table.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+/* SID to code */
+static const uint8_t standard_encoding_to_code [] =
+{
+    0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
+   47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
+   63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
+   79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177,
+  178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196,
+  197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235,
+  241,  245,  248,  249,  250,  251
+};
+
+/* SID to code */
+static const uint8_t expert_encoding_to_code [] =
+{
+    0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0,
+    0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48,
+   49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67,
+   68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191,
+  192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212,
+  213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
+  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244,
+  245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_charset_to_sid [] =
+{
+    0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
+  239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
+  253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
+  267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
+  283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
+  299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
+  315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
+  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
+  341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
+  357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
+  373,  374,  375,  376,  377,  378
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_subset_charset_to_sid [] =
+{
+    0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
+  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
+  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
+  300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
+  150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
+  340,  341,  342,  343,  344,  345,  346
+};
+
+/* code to SID */
+static const uint8_t standard_encoding_to_sid [] =
+{
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
+    17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+    33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+    49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
+    65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
+    81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+    0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
+    0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
+  137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
+    0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
+};
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (standard_encoding_to_code))
+    return (hb_codepoint_t)standard_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (expert_encoding_to_code))
+    return (hb_codepoint_t)expert_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
+    return (hb_codepoint_t)expert_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
+    return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
+{
+  if (code < ARRAY_LENGTH (standard_encoding_to_sid))
+    return (hb_codepoint_t)standard_encoding_to_sid[code];
+  else
+    return CFF_UNDEF_SID;
+}
+
+struct bounds_t
+{
+  void init ()
+  {
+    min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
+    max.set_int (-0x80000000, -0x80000000);
+  }
+
+  void update (const point_t &pt)
+  {
+    if (pt.x < min.x) min.x = pt.x;
+    if (pt.x > max.x) max.x = pt.x;
+    if (pt.y < min.y) min.y = pt.y;
+    if (pt.y > max.y) max.y = pt.y;
+  }
+
+  void merge (const bounds_t &b)
+  {
+    if (empty ())
+      *this = b;
+    else if (!b.empty ())
+    {
+      if (b.min.x < min.x) min.x = b.min.x;
+      if (b.max.x > max.x) max.x = b.max.x;
+      if (b.min.y < min.y) min.y = b.min.y;
+      if (b.max.y > max.y) max.y = b.max.y;
+    }
+  }
+
+  void offset (const point_t &delta)
+  {
+    if (!empty ())
+    {
+      min.move (delta);
+      max.move (delta);
+    }
+  }
+
+  bool empty () const
+  { return (min.x >= max.x) || (min.y >= max.y); }
+
+  point_t min;
+  point_t max;
+};
+
+struct extents_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    path_open = false;
+    cff = _cff;
+    bounds.init ();
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  bool    path_open;
+  bounds_t  bounds;
+
+  const OT::cff1::accelerator_t *cff;
+};
+
+struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.bounds.update (env.get_pt ());
+  }
+
+  static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    /* include control points */
+    param.bounds.update (pt1);
+    param.bounds.update (pt2);
+    env.moveto (pt3);
+    param.bounds.update (env.get_pt ());
+  }
+};
+
+static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
+
+struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    point_t delta;
+    delta.x = env.argStack[n-4];
+    delta.y = env.argStack[n-3];
+    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
+    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
+
+    bounds_t  base_bounds, accent_bounds;
+    if (likely (!env.in_seac && base && accent
+              && _get_bounds (param.cff, base, base_bounds, true)
+              && _get_bounds (param.cff, accent, accent_bounds, true)))
+    {
+      param.bounds.merge (base_bounds);
+      accent_bounds.offset (delta);
+      param.bounds.merge (accent_bounds);
+    }
+    else
+      env.set_error ();
+  }
+};
+
+bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
+{
+  bounds.init ();
+  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
+
+  unsigned int fd = cff->fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*cff->charStrings)[glyph];
+  interp.env.init (str, *cff, fd);
+  interp.env.set_in_seac (in_seac);
+  extents_param_t  param;
+  param.init (cff);
+  if (unlikely (!interp.interpret (param))) return false;
+  bounds = param.bounds;
+  return true;
+}
+
+bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+{
+  bounds_t  bounds;
+
+  if (!_get_bounds (this, glyph, bounds))
+    return false;
+
+  if (bounds.min.x >= bounds.max.x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)bounds.min.x.floor ();
+    extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
+  }
+  if (bounds.min.y >= bounds.max.y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)bounds.max.y.ceil ();
+    extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
+
+struct get_seac_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    cff = _cff;
+    base = 0;
+    accent = 0;
+  }
+
+  bool has_seac () const { return base && accent; }
+
+  const OT::cff1::accelerator_t *cff;
+  hb_codepoint_t  base;
+  hb_codepoint_t  accent;
+};
+
+struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
+    hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
+
+    param.base = param.cff->std_code_to_glyph (base_char);
+    param.accent = param.cff->std_code_to_glyph (accent_char);
+  }
+};
+
+bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd);
+  get_seac_param_t  param;
+  param.init (this);
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.has_seac ())
+  {
+    *base = param.base;
+    *accent = param.accent;
+    return true;
+  }
+  return false;
+}
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
new file mode 100644 (file)
index 0000000..1effdf0
--- /dev/null
@@ -0,0 +1,1299 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_CFF1_TABLE_HH
+#define HB_OT_CFF1_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff1.hh"
+
+namespace CFF {
+
+/*
+ * CFF -- Compact Font Format (CFF)
+ * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
+ */
+#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
+
+#define CFF_UNDEF_SID   CFF_UNDEF_CODE
+
+enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
+enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
+
+typedef CFFIndex<HBUINT16>  CFF1Index;
+template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
+
+typedef CFFIndex<HBUINT16> CFF1Index;
+typedef CFF1Index          CFF1CharStrings;
+typedef FDArray<HBUINT16>  CFF1FDArray;
+typedef Subrs<HBUINT16>    CFF1Subrs;
+
+struct CFF1FDSelect : FDSelect {};
+
+/* Encoding */
+struct Encoding0 {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    if (glyph < nCodes)
+    {
+      return (hb_codepoint_t)codes[glyph];
+    }
+    else
+      return CFF_UNDEF_CODE;
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size * (nCodes + 1); }
+
+  HBUINT8     nCodes;
+  HBUINT8     codes[VAR];
+
+  DEFINE_SIZE_ARRAY(1, codes);
+};
+
+struct Encoding1_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   first;
+  HBUINT8   nLeft;
+
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct Encoding1 {
+  unsigned int get_size () const
+  { return HBUINT8::static_size + Encoding1_Range::static_size * nRanges; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; i < nRanges; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+      {
+       return (hb_codepoint_t)ranges[i].first + glyph;
+      }
+      glyph -= (ranges[i].nLeft + 1);
+    }
+    return CFF_UNDEF_CODE;
+  }
+
+  HBUINT8         nRanges;
+  Encoding1_Range   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (1, ranges);
+};
+
+struct SuppEncoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   code;
+  HBUINT16  glyph;
+
+  DEFINE_SIZE_STATIC (3);
+};
+
+struct CFF1SuppEncData {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
+  }
+
+  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    for (unsigned int i = 0; i < nSups; i++)
+      if (sid == supps[i].glyph)
+       codes.push (supps[i].code);
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
+
+  HBUINT8       nSups;
+  SuppEncoding   supps[VAR];
+
+  DEFINE_SIZE_ARRAY (1, supps);
+};
+
+struct Encoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    unsigned int fmt = format & 0x7F;
+    if (unlikely (fmt > 1))
+      return_trace (false);
+    if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
+      return_trace (false);
+    return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
+  }
+
+  /* serialize a fullset Encoding */
+  bool serialize (hb_serialize_context_t *c, const Encoding &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    Encoding *dest = c->allocate_size<Encoding> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Encoding */
+  bool serialize (hb_serialize_context_t *c,
+                 uint8_t format,
+                 unsigned int enc_count,
+                 const hb_vector_t<code_pair_t>& code_ranges,
+                 const hb_vector_t<code_pair_t>& supp_codes)
+  {
+    TRACE_SERIALIZE (this);
+    Encoding *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format | ((supp_codes.length > 0)? 0x80: 0));
+    if (format == 0)
+    {
+      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      fmt0->nCodes.set (enc_count);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+       hb_codepoint_t code = code_ranges[i].code;
+       for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
+         fmt0->codes[glyph++].set (code++);
+       if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
+         return_trace (false);
+      }
+    }
+    else
+    {
+      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      fmt1->nRanges.set (code_ranges.length);
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+       if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
+         return_trace (false);
+       fmt1->ranges[i].first.set (code_ranges[i].code);
+       fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
+      }
+    }
+    if (supp_codes.length > 0)
+    {
+      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
+      if (unlikely (suppData == nullptr)) return_trace (false);
+      suppData->nSups.set (supp_codes.length);
+      for (unsigned int i = 0; i < supp_codes.length; i++)
+      {
+       suppData->supps[i].code.set (supp_codes[i].code);
+       suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Encoding */
+  static unsigned int calculate_serialized_size (uint8_t format,
+                                                unsigned int enc_count,
+                                                unsigned int supp_count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Encoding0::min_size + HBUINT8::static_size * enc_count;
+    else
+      size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
+    if (supp_count > 0)
+      size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
+    return size;
+  }
+
+  unsigned int get_size () const
+  {
+    unsigned int size = min_size;
+    if (table_format () == 0)
+      size += u.format0.get_size ();
+    else
+      size += u.format1.get_size ();
+    if (has_supplement ())
+      size += suppEncData ().get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    if (table_format () == 0)
+      return u.format0.get_code (glyph);
+    else
+      return u.format1.get_code (glyph);
+  }
+
+  uint8_t table_format () const { return (format & 0x7F); }
+  bool  has_supplement () const { return (format & 0x80) != 0; }
+
+  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    codes.resize (0);
+    if (has_supplement ())
+      suppEncData().get_codes (sid, codes);
+  }
+
+  protected:
+  const CFF1SuppEncData &suppEncData () const
+  {
+    if ((format & 0x7F) == 0)
+      return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes-1]);
+    else
+      return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
+  }
+
+  public:
+  HBUINT8       format;
+
+  union {
+    Encoding0   format0;
+    Encoding1   format1;
+  } u;
+  /* CFF1SuppEncData  suppEncData; */
+
+  DEFINE_SIZE_MIN (1);
+};
+
+/* Charset */
+struct Charset0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0)
+      return 0;
+    else
+      return sids[glyph - 1];
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0)
+      return 0;
+
+    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
+    {
+      if (sids[glyph-1] == sid)
+       return glyph;
+    }
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    assert (num_glyphs > 0);
+    return HBUINT16::static_size * (num_glyphs - 1);
+  }
+
+  HBUINT16  sids[VAR];
+
+  DEFINE_SIZE_ARRAY(0, sids);
+};
+
+template <typename TYPE>
+struct Charset_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16  first;
+  TYPE      nLeft;
+
+  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
+};
+
+template <typename TYPE>
+struct Charset1_2 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    num_glyphs--;
+    for (unsigned int i = 0; num_glyphs > 0; i++)
+    {
+      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
+       return_trace (false);
+      num_glyphs -= (ranges[i].nLeft + 1);
+    }
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0) return 0;
+    glyph--;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+       return (hb_codepoint_t)ranges[i].first + glyph;
+      glyph -= (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0) return 0;
+    hb_codepoint_t  glyph = 1;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph >= num_glyphs)
+       return 0;
+      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
+       return glyph + (sid - ranges[i].first);
+      glyph += (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = HBUINT8::static_size;
+    int glyph = (int)num_glyphs;
+
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; glyph > 0; i++)
+    {
+      glyph -= (ranges[i].nLeft + 1);
+      size += Charset_Range<TYPE>::static_size;
+    }
+
+    return size;
+  }
+
+  Charset_Range<TYPE>   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (0, ranges);
+};
+
+typedef Charset1_2<HBUINT8>     Charset1;
+typedef Charset1_2<HBUINT16>    Charset2;
+typedef Charset_Range<HBUINT8>  Charset1_Range;
+typedef Charset_Range<HBUINT16> Charset2_Range;
+
+struct Charset {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    if (format == 0)
+      return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
+    else if (format == 1)
+      return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
+    else if (likely (format == 2))
+      return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+    else
+      return_trace (false);
+  }
+
+  /* serialize a fullset Charset */
+  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    Charset *dest = c->allocate_size<Charset> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Charset */
+  bool serialize (hb_serialize_context_t *c,
+                 uint8_t format,
+                 unsigned int num_glyphs,
+                 const hb_vector_t<code_pair_t>& sid_ranges)
+  {
+    TRACE_SERIALIZE (this);
+    Charset *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format);
+    if (format == 0)
+    {
+      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+       hb_codepoint_t sid = sid_ranges[i].code;
+       for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
+         fmt0->sids[glyph++].set (sid++);
+      }
+    }
+    else if (format == 1)
+    {
+      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+       if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
+         return_trace (false);
+       fmt1->ranges[i].first.set (sid_ranges[i].code);
+       fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    else /* format 2 */
+    {
+      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt2 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+       if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
+         return_trace (false);
+       fmt2->ranges[i].first.set (sid_ranges[i].code);
+       fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Charset */
+  static unsigned int calculate_serialized_size (
+                       uint8_t format,
+                       unsigned int count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Charset0::min_size + HBUINT16::static_size * (count - 1);
+    else if (format == 1)
+      size += Charset1::min_size + Charset1_Range::static_size * count;
+    else
+      size += Charset2::min_size + Charset2_Range::static_size * count;
+
+    return size;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = min_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 1)
+      size += u.format1.get_size (num_glyphs);
+    else
+      size += u.format2.get_size (num_glyphs);
+    return size;
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (format == 0)
+      return u.format0.get_sid (glyph);
+    else if (format == 1)
+      return u.format1.get_sid (glyph);
+    else
+      return u.format2.get_sid (glyph);
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (format == 0)
+      return u.format0.get_glyph (sid, num_glyphs);
+    else if (format == 1)
+      return u.format1.get_glyph (sid, num_glyphs);
+    else
+      return u.format2.get_glyph (sid, num_glyphs);
+  }
+
+  HBUINT8       format;
+  union {
+    Charset0    format0;
+    Charset1    format1;
+    Charset2    format2;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+struct CFF1StringIndex : CFF1Index
+{
+  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
+                 unsigned int offSize_, const remap_t &sidmap)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
+    {
+      if (!unlikely (c->extend_min (this->count)))
+       return_trace (false);
+      count.set (0);
+      return_trace (true);
+    }
+
+    byte_str_array_t bytesArray;
+    bytesArray.init ();
+    if (!bytesArray.resize (sidmap.get_count ()))
+      return_trace (false);
+    for (unsigned int i = 0; i < strings.count; i++)
+    {
+      hb_codepoint_t  j = sidmap[i];
+      if (j != CFF_UNDEF_CODE)
+       bytesArray[j] = strings[i];
+    }
+
+    bool result = CFF1Index::serialize (c, offSize_, bytesArray);
+    bytesArray.fini ();
+    return_trace (result);
+  }
+
+  /* in parallel to above */
+  unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const remap_t &sidmap) const
+  {
+    offSize = 0;
+    if ((count == 0) || (sidmap.get_count () == 0))
+      return count.static_size;
+
+    unsigned int dataSize = 0;
+    for (unsigned int i = 0; i < count; i++)
+      if (sidmap[i] != CFF_UNDEF_CODE)
+       dataSize += length_at (i);
+
+    offSize = calcOffSize(dataSize);
+    return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
+  }
+};
+
+struct cff1_top_dict_interp_env_t : num_interp_env_t
+{
+  cff1_top_dict_interp_env_t ()
+    : num_interp_env_t(), prev_offset(0), last_offset(0) {}
+
+  unsigned int prev_offset;
+  unsigned int last_offset;
+};
+
+struct name_dict_values_t
+{
+  enum name_dict_val_index_t
+  {
+      version,
+      notice,
+      copyright,
+      fullName,
+      familyName,
+      weight,
+      postscript,
+      fontName,
+      baseFontName,
+      registry,
+      ordering,
+
+      ValCount
+  };
+
+  void init ()
+  {
+    for (unsigned int i = 0; i < ValCount; i++)
+      values[i] = CFF_UNDEF_SID;
+  }
+
+  unsigned int& operator[] (unsigned int i)
+  { assert (i < ValCount); return values[i]; }
+
+  unsigned int operator[] (unsigned int i) const
+  { assert (i < ValCount); return values[i]; }
+
+  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
+  {
+    switch (op) {
+      default: // can't happen - just make some compiler happy
+      case OpCode_version:
+       return version;
+      case OpCode_Notice:
+       return notice;
+      case OpCode_Copyright:
+       return copyright;
+      case OpCode_FullName:
+       return fullName;
+      case OpCode_FamilyName:
+       return familyName;
+      case OpCode_Weight:
+       return weight;
+      case OpCode_PostScript:
+       return postscript;
+      case OpCode_FontName:
+       return fontName;
+      case OpCode_BaseFontName:
+       return baseFontName;
+    }
+  }
+
+  unsigned int  values[ValCount];
+};
+
+struct cff1_top_dict_val_t : op_str_t
+{
+  unsigned int  last_arg_offset;
+};
+
+struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
+{
+  void init ()
+  {
+    top_dict_values_t<cff1_top_dict_val_t>::init ();
+
+    nameSIDs.init ();
+    ros_supplement = 0;
+    cidCount = 8720;
+    EncodingOffset = 0;
+    CharsetOffset = 0;
+    FDSelectOffset = 0;
+    privateDictInfo.init ();
+  }
+  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
+
+  bool is_CID () const
+  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
+
+  name_dict_values_t  nameSIDs;
+  unsigned int    ros_supplement_offset;
+  unsigned int    ros_supplement;
+  unsigned int    cidCount;
+
+  unsigned int    EncodingOffset;
+  unsigned int    CharsetOffset;
+  unsigned int    FDSelectOffset;
+  table_info_t       privateDictInfo;
+};
+
+struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
+{
+  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
+  {
+    cff1_top_dict_val_t  val;
+    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
+
+    switch (op) {
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+       dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_isFixedPitch:
+      case OpCode_ItalicAngle:
+      case OpCode_UnderlinePosition:
+      case OpCode_UnderlineThickness:
+      case OpCode_PaintType:
+      case OpCode_CharstringType:
+      case OpCode_UniqueID:
+      case OpCode_StrokeWidth:
+      case OpCode_SyntheticBase:
+      case OpCode_CIDFontVersion:
+      case OpCode_CIDFontRevision:
+      case OpCode_CIDFontType:
+      case OpCode_UIDBase:
+      case OpCode_FontBBox:
+      case OpCode_XUID:
+      case OpCode_BaseFontBlend:
+       env.clear_args ();
+       break;
+
+      case OpCode_CIDCount:
+       dictval.cidCount = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      case OpCode_ROS:
+       dictval.ros_supplement = env.argStack.pop_uint ();
+       dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
+       dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      case OpCode_Encoding:
+       dictval.EncodingOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       if (unlikely (dictval.EncodingOffset == 0)) return;
+       break;
+
+      case OpCode_charset:
+       dictval.CharsetOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       if (unlikely (dictval.CharsetOffset == 0)) return;
+       break;
+
+      case OpCode_FDSelect:
+       dictval.FDSelectOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      case OpCode_Private:
+       dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+       dictval.privateDictInfo.size = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       env.last_offset = env.str_ref.offset;
+       top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
+       /* Record this operand below if stack is empty, otherwise done */
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+    fontName = CFF_UNDEF_SID;
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t       privateDictInfo;
+  unsigned int    fontName;
+};
+
+struct cff1_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontName:
+       dictval.fontName = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_FontMatrix:
+      case OpCode_PaintType:
+       env.clear_args ();
+       break;
+      case OpCode_Private:
+       dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+       dictval.privateDictInfo.size = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       dict_opset_t::process_op (op, env);
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+template <typename VAL>
+struct cff1_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF1Subrs);
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+       size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+       size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF1Subrs    *localSubrs;
+};
+
+typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
+typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
+
+struct cff1_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+       env.clear_args ();
+       break;
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+       val.single_val = env.argStack.pop_num ();
+       env.clear_args ();
+       break;
+      case OpCode_Subrs:
+       dictval.subrsOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       dict_opset_t::process_op (op, env);
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_private_dict_opset_subset : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+       env.clear_args ();
+       break;
+
+      case OpCode_Subrs:
+       dictval.subrsOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       dict_opset_t::process_op (op, env);
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
+
+typedef CFF1Index CFF1NameIndex;
+typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff1
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 likely (version.major == 1));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff1> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
+
+      if (cff == &Null(OT::cff1))
+      { fini (); return; }
+
+      nameIndex = &cff->nameIndex (cff);
+      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
+      { fini (); return; }
+
+      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
+      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
+      { fini (); return; }
+
+      { /* parse top dict */
+       const byte_str_t topDictStr = (*topDictIndex)[0];
+       if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+       cff1_top_dict_interpreter_t top_interp;
+       top_interp.env.init (topDictStr);
+       topDict.init ();
+       if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      if (is_predef_charset ())
+       charset = &Null(Charset);
+      else
+      {
+       charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
+       if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
+      }
+
+      fdCount = 1;
+      if (is_CID ())
+      {
+       fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
+       fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
+       if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
+           (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
+       { fini (); return; }
+
+       fdCount = fdArray->count;
+      }
+      else
+      {
+       fdArray = &Null(CFF1FDArray);
+       fdSelect = &Null(CFF1FDSelect);
+      }
+
+      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
+      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
+      { fini (); return; }
+
+      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
+      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
+      { fini (); return; }
+
+      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
+
+      if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      privateDicts.resize (fdCount);
+      for (unsigned int i = 0; i < fdCount; i++)
+       privateDicts[i].init ();
+
+      // parse CID font dicts and gather private dicts
+      if (is_CID ())
+      {
+       for (unsigned int i = 0; i < fdCount; i++)
+       {
+         byte_str_t fontDictStr = (*fdArray)[i];
+         if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+         cff1_font_dict_values_t  *font;
+         cff1_font_dict_interpreter_t font_interp;
+         font_interp.env.init (fontDictStr);
+         font = fontDicts.push ();
+         if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
+         font->init ();
+         if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+         PRIVDICTVAL  *priv = &privateDicts[i];
+         const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+         if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+         dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+         priv_interp.env.init (privDictStr);
+         priv->init ();
+         if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+         priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+         if (priv->localSubrs != &Null(CFF1Subrs) &&
+             unlikely (!priv->localSubrs->sanitize (&sc)))
+         { fini (); return; }
+       }
+      }
+      else  /* non-CID */
+      {
+       cff1_top_dict_values_t  *font = &topDict;
+       PRIVDICTVAL  *priv = &privateDicts[0];
+
+       const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+       if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+       dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+       priv_interp.env.init (privDictStr);
+       priv->init ();
+       if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+       priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+       if (priv->localSubrs != &Null(CFF1Subrs) &&
+           unlikely (!priv->localSubrs->sanitize (&sc)))
+       { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+    bool is_CID () const { return topDict.is_CID (); }
+
+    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
+
+    unsigned int std_code_to_glyph (hb_codepoint_t code) const
+    {
+      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
+      if (unlikely (sid == CFF_UNDEF_SID))
+       return 0;
+
+      if (charset != &Null(Charset))
+       return charset->get_glyph (sid, num_glyphs);
+      else if ((topDict.CharsetOffset == ISOAdobeCharset)
+             && (code <= 228 /*zcaron*/)) return sid;
+      return 0;
+    }
+
+    protected:
+    hb_blob_t         *blob;
+    hb_sanitize_context_t   sc;
+
+    public:
+    const Charset         *charset;
+    const CFF1NameIndex     *nameIndex;
+    const CFF1TopDictIndex  *topDictIndex;
+    const CFF1StringIndex   *stringIndex;
+    const CFF1Subrs     *globalSubrs;
+    const CFF1CharStrings   *charStrings;
+    const CFF1FDArray       *fdArray;
+    const CFF1FDSelect      *fdSelect;
+    unsigned int           fdCount;
+
+    cff1_top_dict_values_t       topDict;
+    hb_vector_t<cff1_font_dict_values_t>   fontDicts;
+    hb_vector_t<PRIVDICTVAL>     privateDicts;
+
+    unsigned int           num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
+    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
+  };
+
+  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
+  {
+    void init (hb_face_t *face)
+    {
+      SUPER::init (face);
+      if (blob == nullptr) return;
+
+      const OT::cff1 *cff = this->blob->as<OT::cff1> ();
+      encoding = &Null(Encoding);
+      if (is_CID ())
+      {
+       if (unlikely (charset == &Null(Charset))) { fini (); return; }
+      }
+      else
+      {
+       if (!is_predef_encoding ())
+       {
+         encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
+         if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+       }
+      }
+    }
+
+    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
+
+    hb_codepoint_t  glyph_to_code (hb_codepoint_t glyph) const
+    {
+      if (encoding != &Null(Encoding))
+       return encoding->get_code (glyph);
+      else
+      {
+       hb_codepoint_t  sid = glyph_to_sid (glyph);
+       if (sid == 0) return 0;
+       hb_codepoint_t  code = 0;
+       switch (topDict.EncodingOffset)
+       {
+         case  StandardEncoding:
+           code = lookup_standard_encoding_for_code (sid);
+           break;
+         case  ExpertEncoding:
+           code = lookup_expert_encoding_for_code (sid);
+           break;
+         default:
+           break;
+       }
+       return code;
+      }
+    }
+
+    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
+    {
+      if (charset != &Null(Charset))
+       return charset->get_sid (glyph);
+      else
+      {
+       hb_codepoint_t sid = 0;
+       switch (topDict.CharsetOffset)
+       {
+         case  ISOAdobeCharset:
+           if (glyph <= 228 /*zcaron*/) sid = glyph;
+           break;
+         case  ExpertCharset:
+           sid = lookup_expert_charset_for_sid (glyph);
+           break;
+         case  ExpertSubsetCharset:
+             sid = lookup_expert_subset_charset_for_sid (glyph);
+           break;
+         default:
+           break;
+       }
+       return sid;
+      }
+    }
+
+    const Encoding       *encoding;
+
+    private:
+    typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
+  };
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff1 (plan, &cff_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff_prime);
+
+    return success;
+  }
+
+  protected:
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
+
+  public:
+  FixedVersion<HBUINT8> version;         /* Version of CFF table. set to 0x0100u */
+  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
+  HBUINT8             offSize;   /* offset size (unused?) */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct cff1_accelerator_t : cff1::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF1_TABLE_HH */
diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc
new file mode 100644 (file)
index 0000000..7daa536
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff2-table.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct extents_param_t
+{
+  void init ()
+  {
+    path_open = false;
+    min_x.set_int (0x7FFFFFFF);
+    min_y.set_int (0x7FFFFFFF);
+    max_x.set_int (-0x80000000);
+    max_y.set_int (-0x80000000);
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  void update_bounds (const point_t &pt)
+  {
+    if (pt.x < min_x) min_x = pt.x;
+    if (pt.x > max_x) max_x = pt.x;
+    if (pt.y < min_y) min_y = pt.y;
+    if (pt.y > max_y) max_y = pt.y;
+  }
+
+  bool  path_open;
+  number_t min_x;
+  number_t min_y;
+  number_t max_x;
+  number_t max_y;
+};
+
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.update_bounds (env.get_pt ());
+  }
+
+  static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    /* include control points */
+    param.update_bounds (pt1);
+    param.update_bounds (pt2);
+    env.moveto (pt3);
+    param.update_bounds (env.get_pt ());
+  }
+};
+
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
+
+bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
+                                          hb_codepoint_t glyph,
+                                          hb_glyph_extents_t *extents) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int num_coords;
+  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd, coords, num_coords);
+  extents_param_t  param;
+  param.init ();
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.min_x >= param.max_x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)param.min_x.floor ();
+    extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
+  }
+  if (param.min_y >= param.max_y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)param.max_y.ceil ();
+    extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
new file mode 100644 (file)
index 0000000..a7b0ba9
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_CFF2_TABLE_HH
+#define HB_OT_CFF2_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff2.hh"
+
+namespace CFF {
+
+/*
+ * CFF2 -- Compact Font Format (CFF) Version 2
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
+ */
+#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
+
+typedef CFFIndex<HBUINT32>  CFF2Index;
+template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
+
+typedef CFF2Index         CFF2CharStrings;
+typedef FDArray<HBUINT32> CFF2FDArray;
+typedef Subrs<HBUINT32>   CFF2Subrs;
+
+typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
+typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
+
+struct CFF2FDSelect
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
+                         (format == 0)?
+                         u.format0.sanitize (c, fdcount):
+                           ((format == 3)?
+                           u.format3.sanitize (c, fdcount):
+                           u.format4.sanitize (c, fdcount))));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 3)
+      size += u.format3.get_size ();
+    else
+      size += u.format4.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(CFF2FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else if (format == 3)
+      return u.format3.get_fd (glyph);
+    else
+      return u.format4.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+    FDSelect4   format4;
+  } u;
+
+  DEFINE_SIZE_MIN (2);
+};
+
+struct CFF2VariationStore
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size_ = varStore->get_size ();
+    CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, varStore, size_);
+    return_trace (true);
+  }
+
+  unsigned int get_size () const { return HBUINT16::static_size + size; }
+
+  HBUINT16     size;
+  VariationStore  varStore;
+
+  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
+};
+
+struct cff2_top_dict_values_t : top_dict_values_t<>
+{
+  void init ()
+  {
+    top_dict_values_t<>::init ();
+    vstoreOffset = 0;
+    FDSelectOffset = 0;
+  }
+  void fini () { top_dict_values_t<>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < get_count (); i++)
+    {
+      op_code_t op = get_value (i).op;
+      switch (op)
+      {
+       case OpCode_vstore:
+       case OpCode_FDSelect:
+         size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+         break;
+       default:
+         size += top_dict_values_t<>::calculate_serialized_op_size (get_value (i));
+         break;
+      }
+    }
+    return size;
+  }
+
+  unsigned int  vstoreOffset;
+  unsigned int  FDSelectOffset;
+};
+
+struct cff2_top_dict_opset_t : top_dict_opset_t<>
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_top_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontMatrix:
+       {
+         dict_val_t val;
+         val.init ();
+         dictval.add_op (op, env.str_ref);
+         env.clear_args ();
+       }
+       break;
+
+      case OpCode_vstore:
+       dictval.vstoreOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_FDSelect:
+       dictval.FDSelectOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       SUPER::process_op (op, env, dictval);
+       /* Record this operand below if stack is empty, otherwise done */
+       if (!env.argStack.is_empty ()) return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  typedef top_dict_opset_t<> SUPER;
+};
+
+struct cff2_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t    privateDictInfo;
+};
+
+struct cff2_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_Private:
+       dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+       dictval.privateDictInfo.size = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       SUPER::process_op (op, env);
+       if (!env.argStack.is_empty ())
+         return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+template <typename VAL>
+struct cff2_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF2Subrs);
+    ivs = 0;
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+       size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+       size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF2Subrs   *localSubrs;
+  unsigned int      ivs;
+};
+
+typedef cff2_private_dict_values_base_t<op_str_t> cff2_private_dict_values_subset_t;
+typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values_t;
+
+struct cff2_priv_dict_interp_env_t : num_interp_env_t
+{
+  void init (const byte_str_t &str)
+  {
+    num_interp_env_t::init (str);
+    ivs = 0;
+    seen_vsindex = false;
+  }
+
+  void process_vsindex ()
+  {
+    if (likely (!seen_vsindex))
+    {
+      set_ivs (argStack.pop_uint ());
+    }
+    seen_vsindex = true;
+  }
+
+  unsigned int get_ivs () const { return ivs; }
+  void  set_ivs (unsigned int ivs_) { ivs = ivs_; }
+
+  protected:
+  unsigned int  ivs;
+  bool   seen_vsindex;
+};
+
+struct cff2_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ExpansionFactor:
+      case OpCode_LanguageGroup:
+       val.single_val = env.argStack.pop_num ();
+       env.clear_args ();
+       break;
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+       env.clear_args ();
+       break;
+      case OpCode_Subrs:
+       dictval.subrsOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+      case OpCode_vsindexdict:
+       env.process_vsindex ();
+       dictval.ivs = env.get_ivs ();
+       env.clear_args ();
+       break;
+      case OpCode_blenddict:
+       break;
+
+      default:
+       dict_opset_t::process_op (op, env);
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff2_private_dict_opset_subset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+       env.clear_args ();
+       break;
+
+      case OpCode_blenddict:
+       env.clear_args ();
+       return;
+
+      case OpCode_Subrs:
+       dictval.subrsOffset = env.argStack.pop_uint ();
+       env.clear_args ();
+       break;
+
+      default:
+       SUPER::process_op (op, env);
+       if (!env.argStack.is_empty ()) return;
+       break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 likely (version.major == 2));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff2> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
+
+      if (cff2 == &Null(OT::cff2))
+      { fini (); return; }
+
+      { /* parse top dict */
+       byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+       if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+       cff2_top_dict_interpreter_t top_interp;
+       top_interp.env.init (topDictStr);
+       topDict.init ();
+       if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
+      varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset);
+      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset);
+      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
+      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
+
+      if (((varStore != &Null(CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
+         (charStrings == &Null(CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
+         (globalSubrs == &Null(CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
+         (fdArray == &Null(CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
+         (((fdSelect != &Null(CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      fdCount = fdArray->count;
+      privateDicts.resize (fdCount);
+
+      /* parse font dicts and gather private dicts */
+      for (unsigned int i = 0; i < fdCount; i++)
+      {
+       const byte_str_t fontDictStr = (*fdArray)[i];
+       if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+       cff2_font_dict_values_t  *font;
+       cff2_font_dict_interpreter_t font_interp;
+       font_interp.env.init (fontDictStr);
+       font = fontDicts.push ();
+       if (unlikely (font == &Crap(cff2_font_dict_values_t))) { fini (); return; }
+       font->init ();
+       if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+
+       const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+       if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+       dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t>  priv_interp;
+       priv_interp.env.init(privDictStr);
+       privateDicts[i].init ();
+       if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
+
+       privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
+       if (privateDicts[i].localSubrs != &Null(CFF2Subrs) &&
+         unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
+       { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+
+    protected:
+    hb_blob_t                  *blob;
+    hb_sanitize_context_t      sc;
+
+    public:
+    cff2_top_dict_values_t     topDict;
+    const CFF2Subrs            *globalSubrs;
+    const CFF2VariationStore   *varStore;
+    const CFF2CharStrings      *charStrings;
+    const CFF2FDArray          *fdArray;
+    const CFF2FDSelect         *fdSelect;
+    unsigned int               fdCount;
+
+    hb_vector_t<cff2_font_dict_values_t>     fontDicts;
+    hb_vector_t<PRIVDICTVAL>  privateDicts;
+
+    unsigned int             num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_font_t *font,
+                                 hb_codepoint_t glyph,
+                                 hb_glyph_extents_t *extents) const;
+  };
+
+  typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff2_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff2 (plan, &cff2_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff2_prime);
+
+    return success;
+  }
+
+  public:
+  FixedVersion<HBUINT8>                version;        /* Version of CFF2 table. set to 0x0200u */
+  NNOffsetTo<TopDict, HBUINT8> topDict;        /* headerSize = Offset to Top DICT. */
+  HBUINT16                     topDictSize;    /* Top DICT size */
+
+  public:
+  DEFINE_SIZE_STATIC (5);
+};
+
+struct cff2_accelerator_t : cff2::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF2_TABLE_HH */
index c1903f6..0526c35 100644 (file)
@@ -27,9 +27,8 @@
 #ifndef HB_OT_CMAP_TABLE_HH
 #define HB_OT_CMAP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
 
 /*
  * cmap -- Character to Glyph Index Mapping
  */
 #define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
 
-
 namespace OT {
 
 
 struct CmapSubtableFormat0
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
     if (!gid)
@@ -51,8 +49,14 @@ struct CmapSubtableFormat0
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    for (unsigned int i = 0; i < 256; i++)
+      if (glyphIdArray[i])
+       out->add (i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -78,8 +82,8 @@ struct CmapSubtableFormat4
   };
 
   bool serialize (hb_serialize_context_t *c,
-                  const hb_subset_plan_t *plan,
-                  const hb_vector_t<segment_plan> &segments)
+                 const hb_subset_plan_t *plan,
+                 const hb_vector_t<segment_plan> &segments)
   {
     TRACE_SERIALIZE (this);
 
@@ -88,92 +92,92 @@ struct CmapSubtableFormat4
     this->format.set (4);
     this->length.set (get_sub_table_size (segments));
 
-    this->segCountX2.set (segments.len * 2);
-    this->entrySelector.set (MAX (1u, _hb_bit_storage (segments.len)) - 1);
+    this->segCountX2.set (segments.length * 2);
+    this->entrySelector.set (MAX (1u, hb_bit_storage (segments.length)) - 1);
     this->searchRange.set (2 * (1u << this->entrySelector));
-    this->rangeShift.set (segments.len * 2 > this->searchRange
-                          ? 2 * segments.len - this->searchRange
-                          : 0);
+    this->rangeShift.set (segments.length * 2 > this->searchRange
+                         ? 2 * segments.length - this->searchRange
+                         : 0);
 
-    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
     c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
-    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
-    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.len);
-    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
+    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
+    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
 
     if (id_range_offset == nullptr)
       return_trace (false);
 
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       end_count[i].set (segments[i].end_code);
       start_count[i].set (segments[i].start_code);
       if (segments[i].use_delta)
       {
-        hb_codepoint_t cp = segments[i].start_code;
-        hb_codepoint_t start_gid = 0;
-        if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
-          return_trace (false);
-        id_delta[i].set (start_gid - segments[i].start_code);
+       hb_codepoint_t cp = segments[i].start_code;
+       hb_codepoint_t start_gid = 0;
+       if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
+         return_trace (false);
+       id_delta[i].set (start_gid - segments[i].start_code);
       } else {
-        id_delta[i].set (0);
-        unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
-        HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
-        if (glyph_id_array == nullptr)
-          return_trace (false);
-        // From the cmap spec:
-        //
-        // id_range_offset[i]/2
-        // + (cp - segments[i].start_code)
-        // + (id_range_offset + i)
-        // =
-        // glyph_id_array + (cp - segments[i].start_code)
-        //
-        // So, solve for id_range_offset[i]:
-        //
-        // id_range_offset[i]
-        // =
-        // 2 * (glyph_id_array - id_range_offset - i)
-        id_range_offset[i].set (2 * (
-            glyph_id_array - id_range_offset - i));
-        for (unsigned int j = 0; j < num_codepoints; j++)
-        {
-          hb_codepoint_t cp = segments[i].start_code + j;
-          hb_codepoint_t new_gid;
-          if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-            return_trace (false);
-          glyph_id_array[j].set (new_gid);
-        }
+       id_delta[i].set (0);
+       unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
+       HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
+       if (glyph_id_array == nullptr)
+         return_trace (false);
+       // From the cmap spec:
+       //
+       // id_range_offset[i]/2
+       // + (cp - segments[i].start_code)
+       // + (id_range_offset + i)
+       // =
+       // glyph_id_array + (cp - segments[i].start_code)
+       //
+       // So, solve for id_range_offset[i]:
+       //
+       // id_range_offset[i]
+       // =
+       // 2 * (glyph_id_array - id_range_offset - i)
+       id_range_offset[i].set (2 * (
+           glyph_id_array - id_range_offset - i));
+       for (unsigned int j = 0; j < num_codepoints; j++)
+       {
+         hb_codepoint_t cp = segments[i].start_code + j;
+         hb_codepoint_t new_gid;
+         if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
+           return_trace (false);
+         glyph_id_array[j].set (new_gid);
+       }
       }
     }
 
     return_trace (true);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
+  static size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
   {
     size_t segment_size = 0;
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       // Parallel array entries
       segment_size +=
-            2  // end count
-          + 2  // start count
-          + 2  // delta
-          + 2; // range offset
+           2  // end count
+         + 2  // start count
+         + 2  // delta
+         + 2; // range offset
 
       if (!segments[i].use_delta)
-        // Add bytes for the glyph index array entries for this segment.
-        segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2;
+       // Add bytes for the glyph index array entries for this segment.
+       segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2;
     }
 
     return min_size
-        + 2 // Padding
-        + segment_size;
+       + 2 // Padding
+       + segment_size;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<segment_plan> *segments)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                    hb_vector_t<segment_plan> *segments)
   {
     segment_plan *segment = nullptr;
     hb_codepoint_t last_gid = 0;
@@ -187,24 +191,22 @@ struct CmapSubtableFormat4
        return false;
       }
 
-      if (cp > 0xFFFF) {
-        // We are now outside of unicode BMP, stop adding to this cmap.
-        break;
-      }
+      /* Stop adding to cmap if we are now outside of unicode BMP. */
+      if (cp > 0xFFFF) break;
 
-      if (!segment
-          || cp != segment->end_code + 1u)
+      if (!segment ||
+         cp != segment->end_code + 1u)
       {
-        segment = segments->push ();
-        segment->start_code.set (cp);
-        segment->end_code.set (cp);
-        segment->use_delta = true;
+       segment = segments->push ();
+       segment->start_code.set (cp);
+       segment->end_code.set (cp);
+       segment->use_delta = true;
       } else {
-        segment->end_code.set (cp);
-        if (last_gid + 1u != new_gid)
-          // gid's are not consecutive in this segment so delta
-          // cannot be used.
-          segment->use_delta = false;
+       segment->end_code.set (cp);
+       if (last_gid + 1u != new_gid)
+         // gid's are not consecutive in this segment so delta
+         // cannot be used.
+         segment->use_delta = false;
       }
 
       last_gid = new_gid;
@@ -224,29 +226,32 @@ struct CmapSubtableFormat4
 
   struct accelerator_t
   {
-    inline void init (const CmapSubtableFormat4 *subtable)
+    accelerator_t () {}
+    accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
+    ~accelerator_t () { fini (); }
+
+    void init (const CmapSubtableFormat4 *subtable)
     {
       segCount = subtable->segCountX2 / 2;
-      endCount = subtable->values;
+      endCount = subtable->values.arrayZ;
       startCount = endCount + segCount + 1;
       idDelta = startCount + segCount;
       idRangeOffset = idDelta + segCount;
       glyphIdArray = idRangeOffset + segCount;
       glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
     }
+    void fini () {}
 
-    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
+    bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
     {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
-
       /* Custom two-array bsearch. */
-      int min = 0, max = (int) thiz->segCount - 1;
-      const HBUINT16 *startCount = thiz->startCount;
-      const HBUINT16 *endCount = thiz->endCount;
+      int min = 0, max = (int) this->segCount - 1;
+      const HBUINT16 *startCount = this->startCount;
+      const HBUINT16 *endCount = this->endCount;
       unsigned int i;
       while (min <= max)
       {
-       int mid = (min + max) / 2;
+       int mid = ((unsigned int) min + (unsigned int) max) / 2;
        if (codepoint < startCount[mid])
          max = mid - 1;
        else if (codepoint > endCount[mid])
@@ -261,33 +266,55 @@ struct CmapSubtableFormat4
 
     found:
       hb_codepoint_t gid;
-      unsigned int rangeOffset = thiz->idRangeOffset[i];
+      unsigned int rangeOffset = this->idRangeOffset[i];
       if (rangeOffset == 0)
-       gid = codepoint + thiz->idDelta[i];
+       gid = codepoint + this->idDelta[i];
       else
       {
        /* Somebody has been smoking... */
-       unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
-       if (unlikely (index >= thiz->glyphIdArrayLength))
+       unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+       if (unlikely (index >= this->glyphIdArrayLength))
          return false;
-       gid = thiz->glyphIdArray[index];
+       gid = this->glyphIdArray[index];
        if (unlikely (!gid))
          return false;
-       gid += thiz->idDelta[i];
+       gid += this->idDelta[i];
       }
-
-      *glyph = gid & 0xFFFFu;
+      gid &= 0xFFFFu;
+      if (!gid)
+       return false;
+      *glyph = gid;
       return true;
     }
-
-    static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
+    static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
     {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
-      for (unsigned int i = 0; i < thiz->segCount; i++)
+      return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph);
+    }
+    void collect_unicodes (hb_set_t *out) const
+    {
+      unsigned int count = this->segCount;
+      if (count && this->startCount[count - 1] == 0xFFFFu)
+       count--; /* Skip sentinel segment. */
+      for (unsigned int i = 0; i < count; i++)
       {
-       if (thiz->startCount[i] != 0xFFFFu
-           || thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF)
-         hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+       unsigned int rangeOffset = this->idRangeOffset[i];
+       if (rangeOffset == 0)
+         out->add_range (this->startCount[i], this->endCount[i]);
+       else
+       {
+         for (hb_codepoint_t codepoint = this->startCount[i];
+              codepoint <= this->endCount[i];
+              codepoint++)
+         {
+           unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+           if (unlikely (index >= this->glyphIdArrayLength))
+             break;
+           hb_codepoint_t gid = this->glyphIdArray[index];
+           if (unlikely (!gid))
+             continue;
+           out->add (codepoint);
+         }
+       }
       }
     }
 
@@ -300,14 +327,18 @@ struct CmapSubtableFormat4
     unsigned int glyphIdArrayLength;
   };
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    accelerator_t accel;
-    accel.init (this);
+    accelerator_t accel (this);
     return accel.get_glyph_func (&accel, codepoint, glyph);
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    accelerator_t accel (this);
+    accel.collect_unicodes (out);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -340,7 +371,8 @@ struct CmapSubtableFormat4
   HBUINT16     entrySelector;  /* log2(searchRange/2) */
   HBUINT16     rangeShift;     /* 2 x segCount - searchRange */
 
-  HBUINT16     values[VAR];
+  UnsizedArrayOf<HBUINT16>
+               values;
 #if 0
   HBUINT16     endCount[segCount];     /* End characterCode for each segment,
                                         * last=0xFFFFu. */
@@ -348,7 +380,8 @@ struct CmapSubtableFormat4
   HBUINT16     startCount[segCount];   /* Start character code for each segment. */
   HBINT16              idDelta[segCount];      /* Delta for all character codes in segment. */
   HBUINT16     idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  HBUINT16     glyphIdArray[VAR];      /* Glyph index array (arbitrary length) */
+  UnsizedArrayOf<HBUINT16>
+               glyphIdArray;   /* Glyph index array (arbitrary length) */
 #endif
 
   public:
@@ -370,7 +403,7 @@ struct CmapSubtableLongGroup
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -380,15 +413,16 @@ struct CmapSubtableLongGroup
   HBUINT32             startCharCode;  /* First character code in this group. */
   HBUINT32             endCharCode;    /* Last character code in this group. */
   HBUINT32             glyphID;        /* Glyph index; interpretation depends on
-                                * subtable format. */
+                                        * subtable format. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
+DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
 
 template <typename UINT>
 struct CmapSubtableTrimmed
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     /* Rely on our implicit array bound-checking. */
     hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
@@ -397,8 +431,16 @@ struct CmapSubtableTrimmed
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    hb_codepoint_t start = startCharCode;
+    unsigned int count = glyphIdArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphIdArray[i])
+       out->add (start + i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
@@ -424,37 +466,36 @@ struct CmapSubtableLongSegmented
 {
   friend struct cmap;
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    int i = groups.bsearch (codepoint);
-    if (i == -1)
+    hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
+    if (!gid)
       return false;
-    *glyph = T::group_get_glyph (groups[i], codepoint);
+    *glyph = gid;
     return true;
   }
 
-  inline void get_all_codepoints (hb_set_t *out) const
+  void collect_unicodes (hb_set_t *out) const
   {
     for (unsigned int i = 0; i < this->groups.len; i++) {
-      hb_set_add_range (out,
-                       this->groups[i].startCharCode,
-                       this->groups[i].endCharCode);
+      out->add_range (this->groups[i].startCharCode,
+                     MIN ((hb_codepoint_t) this->groups[i].endCharCode,
+                          (hb_codepoint_t) HB_UNICODE_MAX));
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && groups.sanitize (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         const hb_vector_t<CmapSubtableLongGroup> &group_data)
+  bool serialize (hb_serialize_context_t *c,
+                 const hb_vector_t<CmapSubtableLongGroup> &group_data)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    Supplier<CmapSubtableLongGroup> supplier (group_data.arrayZ, group_data.len);
-    if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
+    if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
     return true;
   }
 
@@ -471,13 +512,14 @@ struct CmapSubtableLongSegmented
 
 struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                               hb_codepoint_t u)
-  { return group.glyphID + (u - group.startCharCode); }
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                        hb_codepoint_t u)
+  { return likely (group.startCharCode <= group.endCharCode) ?
+          group.glyphID + (u - group.startCharCode) : 0; }
 
 
   bool serialize (hb_serialize_context_t *c,
-                  const hb_vector_t<CmapSubtableLongGroup> &groups)
+                 const hb_vector_t<CmapSubtableLongGroup> &groups)
   {
     if (unlikely (!c->extend_min (*this))) return false;
 
@@ -488,13 +530,13 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
     return CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
+  static size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
   {
-    return 16 + 12 * groups.len;
+    return 16 + 12 * groups.length;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<CmapSubtableLongGroup> *groups)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                    hb_vector_t<CmapSubtableLongGroup> *groups)
   {
     CmapSubtableLongGroup *group = nullptr;
 
@@ -509,18 +551,16 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 
       if (!group || !_is_gid_consecutive (group, cp, new_gid))
       {
-        group = groups->push ();
-        group->startCharCode.set (cp);
-        group->endCharCode.set (cp);
-        group->glyphID.set (new_gid);
-      } else
-      {
-        group->endCharCode.set (cp);
+       group = groups->push ();
+       group->startCharCode.set (cp);
+       group->endCharCode.set (cp);
+       group->glyphID.set (new_gid);
       }
+      else group->endCharCode.set (cp);
     }
 
     DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups->len; i++) {
+    for (unsigned int i = 0; i < groups->length; i++) {
       CmapSubtableLongGroup& group = (*groups)[i];
       DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
     }
@@ -529,9 +569,9 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
   }
 
  private:
-  static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group,
-                                         hb_codepoint_t cp,
-                                         hb_codepoint_t new_gid)
+  static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
+                                  hb_codepoint_t cp,
+                                  hb_codepoint_t new_gid)
   {
     return (cp - 1 == group->endCharCode) &&
        new_gid == group->glyphID + (cp - group->startCharCode);
@@ -541,8 +581,8 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 
 struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                               hb_codepoint_t u HB_UNUSED)
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                        hb_codepoint_t u HB_UNUSED)
   { return group.glyphID; }
 };
 
@@ -555,36 +595,52 @@ typedef enum
 
 struct UnicodeValueRange
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     if (codepoint < startUnicodeValue) return -1;
     if (codepoint > startUnicodeValue + additionalCount) return +1;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   HBUINT24     startUnicodeValue;      /* First value in this range. */
-  HBUINT8              additionalCount;        /* Number of additional values in this
+  HBUINT8      additionalCount;        /* Number of additional values in this
                                         * range. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef SortedArrayOf<UnicodeValueRange, HBUINT32> DefaultUVS;
+struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      hb_codepoint_t first = arrayZ[i].startUnicodeValue;
+      hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
+                                (hb_codepoint_t) HB_UNICODE_MAX);
+      out->add_range (first, last);
+    }
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct UVSMapping
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -596,35 +652,48 @@ struct UVSMapping
   DEFINE_SIZE_STATIC (5);
 };
 
-typedef SortedArrayOf<UVSMapping, HBUINT32> NonDefaultUVS;
+struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (arrayZ[i].glyphID);
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct VariationSelectorRecord
 {
-  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
-                                   hb_codepoint_t *glyph,
-                                   const void *base) const
+  glyph_variant_t get_glyph (hb_codepoint_t codepoint,
+                            hb_codepoint_t *glyph,
+                            const void *base) const
   {
-    int i;
-    const DefaultUVS &defaults = base+defaultUVS;
-    i = defaults.bsearch (codepoint);
-    if (i != -1)
+    if ((base+defaultUVS).bfind (codepoint))
       return GLYPH_VARIANT_USE_DEFAULT;
-    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
-    i = nonDefaults.bsearch (codepoint);
-    if (i != -1)
+    const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
+    if (nonDefault.glyphID)
     {
-      *glyph = nonDefaults[i].glyphID;
+      *glyph = nonDefault.glyphID;
        return GLYPH_VARIANT_FOUND;
     }
     return GLYPH_VARIANT_NOT_FOUND;
   }
 
-  inline int cmp (const hb_codepoint_t &variation_selector) const
+  void collect_unicodes (hb_set_t *out, const void *base) const
+  {
+    (base+defaultUVS).collect_unicodes (out);
+    (base+nonDefaultUVS).collect_unicodes (out);
+  }
+
+  int cmp (const hb_codepoint_t &variation_selector) const
   {
     return varSelector.cmp (variation_selector);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -634,23 +703,35 @@ struct VariationSelectorRecord
 
   HBUINT24     varSelector;    /* Variation selector. */
   LOffsetTo<DefaultUVS>
-               defaultUVS;     /* Offset to Default UVS Table. May be 0. */
+               defaultUVS;     /* Offset to Default UVS Table.  May be 0. */
   LOffsetTo<NonDefaultUVS>
-               nonDefaultUVS;  /* Offset to Non-Default UVS Table. May be 0. */
+               nonDefaultUVS;  /* Offset to Non-Default UVS Table.  May be 0. */
   public:
   DEFINE_SIZE_STATIC (11);
 };
 
 struct CmapSubtableFormat14
 {
-  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
-                                           hb_codepoint_t variation_selector,
-                                           hb_codepoint_t *glyph) const
+  glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+                                    hb_codepoint_t variation_selector,
+                                    hb_codepoint_t *glyph) const
   {
-    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
+    return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  void collect_variation_selectors (hb_set_t *out) const
+  {
+    unsigned int count = record.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (record.arrayZ[i].varSelector);
+  }
+  void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                  hb_set_t *out) const
+  {
+    record.bsearch (variation_selector).collect_unicodes (out, this);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -671,8 +752,8 @@ struct CmapSubtable
 {
   /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
 
-  inline bool get_glyph (hb_codepoint_t codepoint,
-                        hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint,
+                 hb_codepoint_t *glyph) const
   {
     switch (u.format) {
     case  0: return u.format0 .get_glyph (codepoint, glyph);
@@ -685,8 +766,21 @@ struct CmapSubtable
     default: return false;
     }
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    switch (u.format) {
+    case  0: u.format0 .collect_unicodes (out); return;
+    case  4: u.format4 .collect_unicodes (out); return;
+    case  6: u.format6 .collect_unicodes (out); return;
+    case 10: u.format10.collect_unicodes (out); return;
+    case 12: u.format12.collect_unicodes (out); return;
+    case 13: u.format13.collect_unicodes (out); return;
+    case 14:
+    default: return;
+    }
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -720,7 +814,7 @@ struct CmapSubtable
 
 struct EncodingRecord
 {
-  inline int cmp (const EncodingRecord &other) const
+  int cmp (const EncodingRecord &other) const
   {
     int ret;
     ret = platformID.cmp (other.platformID);
@@ -730,7 +824,7 @@ struct EncodingRecord
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -747,106 +841,85 @@ struct EncodingRecord
 
 struct cmap
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_cmap;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
-  struct subset_plan {
-    subset_plan(void)
-    {
-      format4_segments.init();
-      format12_groups.init();
-    }
-
-    ~subset_plan(void)
-    {
-      format4_segments.fini();
-      format12_groups.fini();
-    }
-
-    inline size_t final_size() const
+  struct subset_plan
+  {
+    size_t final_size () const
     {
       return 4 // header
-          +  8 * 3 // 3 EncodingRecord
-          +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
-          +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
+         +  8 * 3 // 3 EncodingRecord
+         +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
+         +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
     }
 
-    // Format 4
     hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-    // Format 12
     hb_vector_t<CmapSubtableLongGroup> format12_groups;
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool _create_plan (const hb_subset_plan_t *plan,
+                    subset_plan *cmap_plan) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 likely (version == 0) &&
-                 encodingRecord.sanitize (c, this));
-  }
-
-  inline bool _create_plan (const hb_subset_plan_t *plan,
-                            subset_plan *cmap_plan) const
-  {
-    if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
+    if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
       return false;
 
     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
-  inline bool _subset (const hb_subset_plan_t *plan,
-                       const subset_plan &cmap_subset_plan,
-                      size_t dest_sz,
-                      void *dest) const
+  bool _subset (const hb_subset_plan_t *plan,
+               const subset_plan &cmap_subset_plan,
+               size_t dest_sz,
+               void *dest) const
   {
     hb_serialize_context_t c (dest, dest_sz);
 
-    OT::cmap *cmap = c.start_serialize<OT::cmap> ();
-    if (unlikely (!c.extend_min (*cmap)))
+    cmap *table = c.start_serialize<cmap> ();
+    if (unlikely (!c.extend_min (*table)))
     {
       return false;
     }
 
-    cmap->version.set (0);
+    table->version.set (0);
 
-    if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
+    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
       return false;
 
     // TODO(grieger): Convert the below to a for loop
 
     // Format 4, Plat 0 Encoding Record
-    EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
+    EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
     format4_plat0_rec.platformID.set (0); // Unicode
     format4_plat0_rec.encodingID.set (3);
 
     // Format 4, Plat 3 Encoding Record
-    EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
+    EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
     format4_plat3_rec.platformID.set (3); // Windows
     format4_plat3_rec.encodingID.set (1); // Unicode BMP
 
     // Format 12 Encoding Record
-    EncodingRecord &format12_rec = cmap->encodingRecord[2];
+    EncodingRecord &format12_rec = table->encodingRecord[2];
     format12_rec.platformID.set (3); // Windows
     format12_rec.encodingID.set (10); // Unicode UCS-4
 
     // Write out format 4 sub table
     {
-      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
       format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
       subtable.u.format.set (4);
 
       CmapSubtableFormat4 &format4 = subtable.u.format4;
       if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
-        return false;
+       return false;
     }
 
     // Write out format 12 sub table.
     {
-      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
       subtable.u.format.set (12);
 
       CmapSubtableFormat12 &format12 = subtable.u.format12;
       if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
-        return false;
+       return false;
     }
 
     c.end_serialize ();
@@ -854,7 +927,7 @@ struct cmap
     return true;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     subset_plan cmap_subset_plan;
 
@@ -865,7 +938,7 @@ struct cmap
     }
 
     // We now know how big our blob needs to be
-    size_t dest_sz = cmap_subset_plan.final_size();
+    size_t dest_sz = cmap_subset_plan.final_size ();
     void *dest = malloc (dest_sz);
     if (unlikely (!dest)) {
       DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
@@ -880,147 +953,159 @@ struct cmap
     }
 
     // all done, write the blob into dest
-    hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest,
-                                            dest_sz,
-                                            HB_MEMORY_MODE_READONLY,
-                                            dest,
-                                            free);
+    hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest,
+                                           dest_sz,
+                                           HB_MEMORY_MODE_READONLY,
+                                           dest,
+                                           free);
     bool result =  plan->add_table (HB_OT_TAG_cmap, cmap_prime);
     hb_blob_destroy (cmap_prime);
     return result;
   }
 
-  struct accelerator_t
+  const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
   {
-    inline void init (hb_face_t *face)
+    if (symbol) *symbol = false;
+
+    const CmapSubtable *subtable;
+
+    /* 32-bit subtables. */
+    if ((subtable = this->find_subtable (3, 10))) return subtable;
+    if ((subtable = this->find_subtable (0, 6))) return subtable;
+    if ((subtable = this->find_subtable (0, 4))) return subtable;
+
+    /* 16-bit subtables. */
+    if ((subtable = this->find_subtable (3, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 3))) return subtable;
+    if ((subtable = this->find_subtable (0, 2))) return subtable;
+    if ((subtable = this->find_subtable (0, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 0))) return subtable;
+
+    /* Symbol subtable. */
+    if ((subtable = this->find_subtable (3, 0)))
     {
-      this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
-      const OT::cmap *cmap = this->blob->as<OT::cmap> ();
-      const OT::CmapSubtable *subtable = nullptr;
-      const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
-
-      bool symbol = false;
-      /* 32-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 10);
-      if (!subtable) subtable = cmap->find_subtable (0, 6);
-      if (!subtable) subtable = cmap->find_subtable (0, 4);
-      /* 16-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 3);
-      if (!subtable) subtable = cmap->find_subtable (0, 2);
-      if (!subtable) subtable = cmap->find_subtable (0, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 0);
-      if (!subtable)
-      {
-       subtable = cmap->find_subtable (3, 0);
-       if (subtable) symbol = true;
-      }
-      /* Meh. */
-      if (!subtable) subtable = &Null(OT::CmapSubtable);
+      if (symbol) *symbol = true;
+      return subtable;
+    }
+
+    /* Meh. */
+    return &Null (CmapSubtable);
+  }
 
-      /* UVS subtable. */
-      if (!subtable_uvs)
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
+      bool symbol;
+      this->subtable = table->find_best_subtable (&symbol);
+      this->subtable_uvs = &Null (CmapSubtableFormat14);
       {
-       const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+       const CmapSubtable *st = table->find_subtable (0, 5);
        if (st && st->u.format == 14)
          subtable_uvs = &st->u.format14;
       }
-      /* Meh. */
-      if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
-
-      this->uvs_table = subtable_uvs;
 
       this->get_glyph_data = subtable;
       if (unlikely (symbol))
       {
-       this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-       this->get_all_codepoints_func = null_get_all_codepoints_func;
+       this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
       } else {
        switch (subtable->u.format) {
        /* Accelerate format 4 and format 12. */
        default:
-         this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
-         this->get_all_codepoints_func = null_get_all_codepoints_func;
+         this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
          break;
        case 12:
-         this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
-         this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
+         this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
          break;
        case  4:
          {
            this->format4_accel.init (&subtable->u.format4);
            this->get_glyph_data = &this->format4_accel;
-           this->get_glyph_func = this->format4_accel.get_glyph_func;
-           this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func;
+           this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
          }
          break;
        }
       }
     }
 
-    inline void fini (void)
-    {
-      hb_blob_destroy (this->blob);
-    }
+    void fini () { this->table.destroy (); }
 
-    inline bool get_nominal_glyph (hb_codepoint_t  unicode,
+    bool get_nominal_glyph (hb_codepoint_t  unicode,
                                   hb_codepoint_t *glyph) const
     {
-      return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+      if (unlikely (!this->get_glyph_funcZ)) return false;
+      return this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
     }
+    unsigned int get_nominal_glyphs (unsigned int count,
+                                    const hb_codepoint_t *first_unicode,
+                                    unsigned int unicode_stride,
+                                    hb_codepoint_t *first_glyph,
+                                    unsigned int glyph_stride) const
+    {
+      if (unlikely (!this->get_glyph_funcZ)) return 0;
 
-    inline bool get_variation_glyph (hb_codepoint_t  unicode,
-                                    hb_codepoint_t  variation_selector,
-                                    hb_codepoint_t *glyph) const
+      hb_cmap_get_glyph_func_t get_glyph_funcZ = this->get_glyph_funcZ;
+      const void *get_glyph_data = this->get_glyph_data;
+
+      unsigned int done;
+      for (done = 0;
+          done < count && get_glyph_funcZ (get_glyph_data, *first_unicode, first_glyph);
+          done++)
+      {
+       first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+       first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      }
+      return done;
+    }
+
+    bool get_variation_glyph (hb_codepoint_t  unicode,
+                             hb_codepoint_t  variation_selector,
+                             hb_codepoint_t *glyph) const
     {
-      switch (this->uvs_table->get_glyph_variant (unicode,
-                                                 variation_selector,
-                                                 glyph))
+      switch (this->subtable_uvs->get_glyph_variant (unicode,
+                                                    variation_selector,
+                                                    glyph))
       {
-       case OT::GLYPH_VARIANT_NOT_FOUND:               return false;
-       case OT::GLYPH_VARIANT_FOUND:           return true;
-       case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
+       case GLYPH_VARIANT_NOT_FOUND:   return false;
+       case GLYPH_VARIANT_FOUND:       return true;
+       case GLYPH_VARIANT_USE_DEFAULT: break;
       }
 
       return get_nominal_glyph (unicode, glyph);
     }
 
-    inline void get_all_codepoints (hb_set_t *out) const
+    void collect_unicodes (hb_set_t *out) const
+    {
+      subtable->collect_unicodes (out);
+    }
+    void collect_variation_selectors (hb_set_t *out) const
+    {
+      subtable_uvs->collect_variation_selectors (out);
+    }
+    void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                    hb_set_t *out) const
     {
-      this->get_all_codepoints_func (get_glyph_data, out);
+      subtable_uvs->collect_variation_unicodes (variation_selector, out);
     }
 
     protected:
     typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
                                              hb_codepoint_t codepoint,
                                              hb_codepoint_t *glyph);
-    typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj,
-                                                      hb_set_t *out);
-
-    static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out)
-    {
-      // NOOP
-    }
 
     template <typename Type>
-    static inline bool get_glyph_from (const void *obj,
-                                      hb_codepoint_t codepoint,
-                                      hb_codepoint_t *glyph)
+    static bool get_glyph_from (const void *obj,
+                               hb_codepoint_t codepoint,
+                               hb_codepoint_t *glyph)
     {
       const Type *typed_obj = (const Type *) obj;
       return typed_obj->get_glyph (codepoint, glyph);
     }
 
     template <typename Type>
-    static inline void get_all_codepoints_from (const void *obj,
-                                               hb_set_t *out)
-    {
-      const Type *typed_obj = (const Type *) obj;
-      typed_obj->get_all_codepoints (out);
-    }
-
-    template <typename Type>
-    static inline bool get_glyph_from_symbol (const void *obj,
+    static bool get_glyph_from_symbol (const void *obj,
                                              hb_codepoint_t codepoint,
                                              hb_codepoint_t *glyph)
     {
@@ -1042,33 +1127,41 @@ struct cmap
     }
 
     private:
-    hb_cmap_get_glyph_func_t get_glyph_func;
+    hb_nonnull_ptr_t<const CmapSubtable> subtable;
+    hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
+
+    hb_cmap_get_glyph_func_t get_glyph_funcZ;
     const void *get_glyph_data;
-    hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
 
-    OT::CmapSubtableFormat4::accelerator_t format4_accel;
+    CmapSubtableFormat4::accelerator_t format4_accel;
 
-    const OT::CmapSubtableFormat14 *uvs_table;
-    hb_blob_t *blob;
+    hb_blob_ptr_t<cmap> table;
   };
 
   protected:
 
-  inline const CmapSubtable *find_subtable (unsigned int platform_id,
-                                           unsigned int encoding_id) const
+  const CmapSubtable *find_subtable (unsigned int platform_id,
+                                    unsigned int encoding_id) const
   {
     EncodingRecord key;
     key.platformID.set (platform_id);
     key.encodingID.set (encoding_id);
 
-    /* Note: We can use bsearch, but since it has no performance
-     * implications, we use lsearch and as such accept fonts with
-     * unsorted subtable list. */
-    int result = encodingRecord./*bsearch*/lsearch (key);
-    if (result == -1 || !encodingRecord[result].subtable)
+    const EncodingRecord &result = encodingRecord.bsearch (key);
+    if (!result.subtable)
       return nullptr;
 
-    return &(this+encodingRecord[result].subtable);
+    return &(this+result.subtable);
+  }
+
+  public:
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 likely (version == 0) &&
+                 encodingRecord.sanitize (c, this));
   }
 
   protected:
@@ -1079,6 +1172,7 @@ struct cmap
   DEFINE_SIZE_ARRAY (4, encodingRecord);
 };
 
+struct cmap_accelerator_t : cmap::accelerator_t {};
 
 } /* namespace OT */
 
index d1dd9de..333ceaa 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_COLOR_CBDT_TABLE_HH
 #define HB_OT_COLOR_CBDT_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * CBLC -- Color Bitmap Location
@@ -45,18 +45,18 @@ namespace OT {
 
 struct SmallGlyphMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline void get_extents (hb_glyph_extents_t *extents) const
+  void get_extents (hb_glyph_extents_t *extents) const
   {
     extents->x_bearing = bearingX;
     extents->y_bearing = bearingY;
     extents->width = width;
-    extents->height = -height;
+    extents->height = - (hb_position_t) height;
   }
 
   HBUINT8      height;
@@ -79,7 +79,7 @@ struct BigGlyphMetrics : SmallGlyphMetrics
 
 struct SBitLineMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -108,7 +108,7 @@ struct SBitLineMetrics
 
 struct IndexSubtableHeader
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -124,11 +124,11 @@ struct IndexSubtableHeader
 template <typename OffsetType>
 struct IndexSubtableFormat1Or3
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+                 offsetArrayZ.sanitize (c, glyph_count + 1));
   }
 
   bool get_image_data (unsigned int idx,
@@ -144,7 +144,8 @@ struct IndexSubtableFormat1Or3
   }
 
   IndexSubtableHeader  header;
-  Offset<OffsetType>   offsetArrayZ[VAR];
+  UnsizedArrayOf<Offset<OffsetType> >
+                       offsetArrayZ;
   public:
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
@@ -154,7 +155,7 @@ struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {};
 
 struct IndexSubtable
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     if (!u.header.sanitize (c)) return_trace (false);
@@ -165,7 +166,7 @@ struct IndexSubtable
     }
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
   {
     switch (u.header.indexFormat) {
     case 2: case 5: /* TODO */
@@ -200,29 +201,28 @@ struct IndexSubtable
 
 struct IndexSubtableRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                  firstGlyphIndex <= lastGlyphIndex &&
-                 offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+                 offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents,
+                   const void *base) const
   {
-    return (this+offsetToSubtable).get_extents (extents);
+    return (base+offsetToSubtable).get_extents (extents);
   }
 
-  bool get_image_data (unsigned int gid,
+  bool get_image_data (unsigned int  gid,
+                      const void   *base,
                       unsigned int *offset,
                       unsigned int *length,
                       unsigned int *format) const
   {
-    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
-    {
-      return false;
-    }
-    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+    if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false;
+    return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
                                                   offset, length, format);
   }
 
@@ -237,15 +237,10 @@ struct IndexSubtableArray
 {
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
-      return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
-       return_trace (false);
-    return_trace (true);
+    return_trace (indexSubtablesZ.sanitize (c, count, this));
   }
 
   public:
@@ -255,17 +250,14 @@ struct IndexSubtableArray
     {
       unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
       unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
         return &indexSubtablesZ[i];
-      }
     }
     return nullptr;
   }
 
   protected:
-  IndexSubtableRecord  indexSubtablesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
+  UnsizedArrayOf<IndexSubtableRecord>  indexSubtablesZ;
 };
 
 struct BitmapSizeTable
@@ -273,23 +265,25 @@ struct BitmapSizeTable
   friend struct CBLC;
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                  indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
-                 c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
                  horizontal.sanitize (c) &&
                  vertical.sanitize (c));
   }
 
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
+  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
+                                        const void *base,
+                                        const void **out_base) const
   {
+    *out_base = &(base+indexSubtableArrayOffset);
     return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
   }
 
   protected:
-  LOffsetTo<IndexSubtableArray>
+  LNNOffsetTo<IndexSubtableArray>
                        indexSubtableArrayOffset;
   HBUINT32             indexTablesSize;
   HBUINT32             numberOfIndexSubtables;
@@ -338,9 +332,9 @@ struct CBLC
 {
   friend struct CBDT;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -349,25 +343,30 @@ struct CBLC
   }
 
   protected:
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
-                                        unsigned int *x_ppem, unsigned int *y_ppem) const
+  const BitmapSizeTable &choose_strike (hb_font_t *font) const
   {
-    /* TODO: Make it possible to select strike. */
+    unsigned count = sizeTables.len;
+    if (unlikely (!count))
+      return Null(BitmapSizeTable);
+
+    unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+    if (!requested_ppem)
+      requested_ppem = 1<<30; /* Choose largest strike. */
+    unsigned int best_i = 0;
+    unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
 
-    unsigned int count = sizeTables.len;
-    for (uint32_t i = 0; i < count; ++i)
+    for (unsigned int i = 1; i < count; i++)
     {
-      unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
+      unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
+      if ((requested_ppem <= ppem && ppem < best_ppem) ||
+         (requested_ppem > best_ppem && ppem > best_ppem))
       {
-       *x_ppem = sizeTables[i].ppemX;
-       *y_ppem = sizeTables[i].ppemY;
-       return sizeTables[i].find_table (glyph, this);
+       best_i = i;
+       best_ppem = ppem;
       }
     }
 
-    return nullptr;
+    return sizeTables[best_i];
   }
 
   protected:
@@ -379,60 +378,42 @@ struct CBLC
 
 struct CBDT
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 likely (version.major == 2 || version.major == 3));
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT;
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      upem = hb_face_get_upem (face);
-
-      cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
-      cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
-      cbdt_len = hb_blob_get_length (cbdt_blob);
-
-      if (hb_blob_get_length (cblc_blob) == 0) {
-       cblc = nullptr;
-       cbdt = nullptr;
-       return;  /* Not a bitmap font. */
-      }
-      cblc = cblc_blob->as<CBLC> ();
-      cbdt = cbdt_blob->as<CBDT> ();
+      cblc = hb_sanitize_context_t().reference_table<CBLC> (face);
+      cbdt = hb_sanitize_context_t().reference_table<CBDT> (face);
 
+      upem = hb_face_get_upem (face);
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (this->cblc_blob);
-      hb_blob_destroy (this->cbdt_blob);
+      this->cblc.destroy ();
+      this->cbdt.destroy ();
     }
 
-    inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+    bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
+                     hb_glyph_extents_t *extents) const
     {
-      unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-      if (!cblc)
-       return false;  // Not a color bitmap font.
-
-      const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-      if (!subtable_record || !x_ppem || !y_ppem)
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
        return false;
 
-      if (subtable_record->get_extents (extents))
+      if (subtable_record->get_extents (extents, base))
        return true;
 
       unsigned int image_offset = 0, image_length = 0, image_format = 0;
-      if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
        return false;
 
       {
+       unsigned int cbdt_len = cbdt.get_length ();
        if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
          return false;
 
@@ -441,98 +422,114 @@ struct CBDT
          case 17: {
            if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
              return false;
-
            const GlyphBitmapDataFormat17& glyphFormat17 =
                StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
            glyphFormat17.glyphMetrics.get_extents (extents);
+           break;
+         }
+         case 18: {
+           if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+             return false;
+           const GlyphBitmapDataFormat18& glyphFormat18 =
+               StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+           glyphFormat18.glyphMetrics.get_extents (extents);
+           break;
          }
-         break;
          default:
            // TODO: Support other image formats.
            return false;
        }
       }
 
-      /* Convert to the font units. */
-      extents->x_bearing *= upem / (float) x_ppem;
-      extents->y_bearing *= upem / (float) y_ppem;
-      extents->width *= upem / (float) x_ppem;
-      extents->height *= upem / (float) y_ppem;
+      /* Convert to font units. */
+      double x_scale = upem / (double) strike.ppemX;
+      double y_scale = upem / (double) strike.ppemY;
+      extents->x_bearing = round (extents->x_bearing * x_scale);
+      extents->y_bearing = round (extents->y_bearing * y_scale);
+      extents->width = round (extents->width * x_scale);
+      extents->height = round (extents->height * y_scale);
 
       return true;
     }
 
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-        unsigned int group, unsigned int gid)) const
+    hb_blob_t* reference_png (hb_font_t      *font,
+                                    hb_codepoint_t  glyph) const
     {
-      if (!cblc)
-       return;  // Not a color bitmap font.
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
+       return hb_blob_get_empty ();
+
+      unsigned int image_offset = 0, image_length = 0, image_format = 0;
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
+       return hb_blob_get_empty ();
 
-      for (unsigned int i = 0; i < cblc->sizeTables.len; ++i)
       {
-        const BitmapSizeTable &sizeTable = cblc->sizeTables[i];
-        const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset;
-        for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j)
-        {
-          const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j];
-          for (unsigned int gid = subtable_record.firstGlyphIndex;
-                gid <= subtable_record.lastGlyphIndex; ++gid)
-          {
-            unsigned int image_offset = 0, image_length = 0, image_format = 0;
-
-            if (!subtable_record.get_image_data (gid,
-                  &image_offset, &image_length, &image_format))
-              continue;
-
-            switch (image_format)
-            {
-            case 17: {
-              const GlyphBitmapDataFormat17& glyphFormat17 =
-                StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat17.data.arrayZ,
-                glyphFormat17.data.len, i, gid);
-            }
-            break;
-            case 18: {
-              const GlyphBitmapDataFormat18& glyphFormat18 =
-                StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat18.data.arrayZ,
-                glyphFormat18.data.len, i, gid);
-            }
-            break;
-            case 19: {
-              const GlyphBitmapDataFormat19& glyphFormat19 =
-                StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat19.data.arrayZ,
-                glyphFormat19.data.len, i, gid);
-            }
-            break;
-            default:
-              continue;
-            }
-          }
-        }
+       unsigned int cbdt_len = cbdt.get_length ();
+       if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+         return hb_blob_get_empty ();
+
+       switch (image_format)
+       {
+         case 17: {
+           if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
+             return hb_blob_get_empty ();
+           const GlyphBitmapDataFormat17& glyphFormat17 =
+             StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+           return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                           image_offset + GlyphBitmapDataFormat17::min_size,
+                                           glyphFormat17.data.len);
+         }
+         case 18: {
+           if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+             return hb_blob_get_empty ();
+           const GlyphBitmapDataFormat18& glyphFormat18 =
+             StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+           return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                           image_offset + GlyphBitmapDataFormat18::min_size,
+                                           glyphFormat18.data.len);
+         }
+         case 19: {
+           if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
+             return hb_blob_get_empty ();
+           const GlyphBitmapDataFormat19& glyphFormat19 =
+             StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
+           return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                           image_offset + GlyphBitmapDataFormat19::min_size,
+                                           glyphFormat19.data.len);
+         }
+       }
       }
+
+      return hb_blob_get_empty ();
     }
 
+    bool has_data () const { return cbdt.get_length (); }
+
     private:
-    hb_blob_t *cblc_blob;
-    hb_blob_t *cbdt_blob;
-    const CBLC *cblc;
-    const CBDT *cbdt;
+    hb_blob_ptr_t<CBLC> cblc;
+    hb_blob_ptr_t<CBDT> cbdt;
 
-    unsigned int cbdt_len;
     unsigned int upem;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 likely (version.major == 2 || version.major == 3));
+  }
 
   protected:
-  FixedVersion<>       version;
-  HBUINT8              dataZ[VAR];
+  FixedVersion<>               version;
+  UnsizedArrayOf<HBUINT8>      dataZ;
   public:
   DEFINE_SIZE_ARRAY(4, dataZ);
 };
 
+struct CBDT_accelerator_t : CBDT::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_CBDT_TABLE_HH */
index ce6702d..a57911a 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_COLR_TABLE_HH
 #define HB_OT_COLOR_COLR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * COLR -- Color
@@ -39,101 +39,97 @@ namespace OT {
 
 struct LayerRecord
 {
-  friend struct COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  protected:
-  GlyphID      glyphid;        /* Glyph ID of layer glyph */
-  HBUINT16     colorIdx;       /* Index value to use with a selected color palette */
+  public:
+  GlyphID      glyphId;        /* Glyph ID of layer glyph */
+  Index                colorIdx;       /* Index value to use with a
+                                * selected color palette.
+                                * An index value of 0xFFFF
+                                * is a special case indicating
+                                * that the text foreground
+                                * color (defined by a
+                                * higher-level client) should
+                                * be used and shall not be
+                                * treated as actual index
+                                * into CPAL ColorRecord array. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseGlyphRecord
 {
-  friend struct COLR;
+  int cmp (hb_codepoint_t g) const
+  { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  inline int cmp (hb_codepoint_t g) const {
-    return g < glyphid ? -1 : g > glyphid ? 1 : 0;
-  }
-
-  protected:
-  GlyphID      glyphid;        /* Glyph ID of reference glyph */
-  HBUINT16     firstLayerIdx;  /* Index to the layer record */
-  HBUINT16     numLayers;      /* Number of color layers associated with this glyph */
+  public:
+  GlyphID      glyphId;        /* Glyph ID of reference glyph */
+  HBUINT16     firstLayerIdx;  /* Index (from beginning of
+                                * the Layer Records) to the
+                                * layer record. There will be
+                                * numLayers consecutive entries
+                                * for this base glyph. */
+  HBUINT16     numLayers;      /* Number of color layers
+                                * associated with this glyph */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-static int compare_bgr (const void *pa, const void *pb)
-{
-  const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
-  const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
-  return b->cmp (*a);
-}
-
 struct COLR
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_COLR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
-                         (this+layersZ).sanitize (c, numLayers)));
-  }
+  bool has_data () const { return numBaseGlyphs; }
 
-  inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
-                                    unsigned int *first_layer /* OUT */,
-                                    unsigned int *num_layers /* OUT */) const
+  unsigned int get_glyph_layers (hb_codepoint_t       glyph,
+                                unsigned int         start_offset,
+                                unsigned int        *count, /* IN/OUT.  May be NULL. */
+                                hb_ot_color_layer_t *layers /* OUT.     May be NULL. */) const
   {
-    const BaseGlyphRecord* record;
-    record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
-                                         sizeof (BaseGlyphRecord), compare_bgr);
-    if (unlikely (!record))
-      return false;
-
-    *first_layer = record->firstLayerIdx;
-    *num_layers = record->numLayers;
-    return true;
-  }
+    const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
 
-  inline bool get_layer_record (unsigned int record,
-                               hb_codepoint_t *glyph_id /* OUT */,
-                               unsigned int *palette_index /* OUT */) const
-  {
-    if (unlikely (record >= numLayers))
+    hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
+    hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
+                                                                      record.numLayers);
+    if (count)
     {
-      *glyph_id = 0;
-      *palette_index = 0xFFFF;
-      return false;
+      hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
+      *count = segment_layers.length;
+      for (unsigned int i = 0; i < segment_layers.length; i++)
+      {
+        layers[i].glyph = segment_layers.arrayZ[i].glyphId;
+        layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
+      }
     }
-    const LayerRecord &layer = (this+layersZ)[record];
-    *glyph_id = layer.glyphid;
-    *palette_index = layer.colorIdx;
-    return true;
+    return glyph_layers.length;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+                         (this+layersZ).sanitize (c, numLayers)));
   }
 
   protected:
-  HBUINT16     version;        /* Table version number */
-  HBUINT16     numBaseGlyphs;  /* Number of Base Glyph Records */
-  LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
+  HBUINT16     version;        /* Table version number (starts at 0). */
+  HBUINT16     numBaseGlyphs;  /* Number of Base Glyph Records. */
+  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord> >
                baseGlyphsZ;    /* Offset to Base Glyph records. */
-  LOffsetTo<UnsizedArrayOf<LayerRecord> >
-               layersZ;        /* Offset to Layer Records */
-  HBUINT16     numLayers;      /* Number of Layer Records */
+  LNNOffsetTo<UnsizedArrayOf<LayerRecord> >
+               layersZ;        /* Offset to Layer Records. */
+  HBUINT16     numLayers;      /* Number of Layer Records. */
   public:
   DEFINE_SIZE_STATIC (14);
 };
index 2c31274..4070493 100644 (file)
 #ifndef HB_OT_COLOR_CPAL_TABLE_HH
 #define HB_OT_COLOR_CPAL_TABLE_HH
 
-#include "hb-open-type-private.hh"
-
-
-/*
- * Following parts to be moved to a public header.
- */
-
-/**
- * hb_ot_color_t:
- * ARGB data type for holding color values.
- *
- * Since: REPLACEME
- */
-typedef uint32_t hb_ot_color_t;
-
-
-/**
- * hb_ot_color_palette_flags_t:
- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
- *
- * Since: REPLACEME
- */
-typedef enum { /*< flags >*/
-  HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
-} hb_ot_color_palette_flags_t;
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_count (hb_face_t *face);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN hb_ot_color_palette_flags_t
-// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_colors (hb_face_t       *face,
-//                             unsigned int     palette, /* default=0 */
-//                             unsigned int     start_offset,
-//                             unsigned int    *color_count /* IN/OUT */,
-//                             hb_ot_color_t   *colors /* OUT */);
-
-
-
+#include "hb-open-type.hh"
+#include "hb-ot-color.h"
+#include "hb-ot-name.h"
 
 
 /*
@@ -92,43 +47,57 @@ struct CPALV1Tail
 {
   friend struct CPAL;
 
-  inline bool
-  sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const
+  private:
+  hb_ot_color_palette_flags_t get_palette_flags (const void *base,
+                                                unsigned int palette_index,
+                                                unsigned int palette_count) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 (base+paletteFlagsZ).sanitize (c, palettes) &&
-                 (base+paletteLabelZ).sanitize (c, palettes) &&
-                 (base+paletteEntryLabelZ).sanitize (c, palettes));
+    if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
+    return (hb_ot_color_palette_flags_t) (uint32_t)
+          (base+paletteFlagsZ).as_array (palette_count)[palette_index];
   }
 
-  private:
-  inline hb_ot_color_palette_flags_t
-  get_palette_flags (const void *base, unsigned int palette) const
+  hb_ot_name_id_t get_palette_name_id (const void *base,
+                                      unsigned int palette_index,
+                                      unsigned int palette_count) const
   {
-    // range checked at the CPAL caller
-    return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette];
+    if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
   }
 
-  inline unsigned int
-  get_palette_name_id (const void *base, unsigned int palette) const
+  hb_ot_name_id_t get_color_name_id (const void *base,
+                                    unsigned int color_index,
+                                    unsigned int color_count) const
   {
-    // range checked at the CPAL caller
-    return (base+paletteLabelZ)[palette];
+    if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+colorLabelsZ).as_array (color_count)[color_index];
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c,
+                const void *base,
+                unsigned int palette_count,
+                unsigned int color_count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 (!paletteFlagsZ  || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
+                 (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
+                 (!colorLabelsZ   || (base+colorLabelsZ).sanitize (c, color_count)));
   }
 
   protected:
-  LOffsetTo<UnsizedArrayOf<HBUINT32> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT32> >
                paletteFlagsZ;          /* Offset from the beginning of CPAL table to
                                         * the Palette Type Array. Set to 0 if no array
                                         * is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-               paletteLabelZ;          /* Offset from the beginning of CPAL table to
-                                        * the Palette Labels Array. Set to 0 if no
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+               paletteLabelsZ;         /* Offset from the beginning of CPAL table to
+                                        * the palette labels array. Set to 0 if no
                                         * array is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-               paletteEntryLabelZ;     /* Offset from the beginning of CPAL table to
-                                        * the Palette Entry Label Array. Set to 0
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+               colorLabelsZ;           /* Offset from the beginning of CPAL table to
+                                        * the color labels array. Set to 0
                                         * if no array is provided. */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -138,76 +107,76 @@ typedef HBUINT32 BGRAColor;
 
 struct CPAL
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CPAL;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) &&  // it checks colorRecordIndices also
-                                               // see #get_size
-                   (this+colorRecordsZ).sanitize (c, numColorRecords))))
-      return_trace (false);
-
-    // Check for indices sanity so no need for doing it runtime
-    for (unsigned int i = 0; i < numPalettes; ++i)
-      if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
-       return_trace (false);
-
-    // If version is zero, we are done here; otherwise we need to check tail also
-    if (version == 0)
-      return_trace (true);
-
-    const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
-    return_trace (likely (v1.sanitize (c, this, numPalettes)));
-  }
+  bool has_data () const { return numPalettes; }
 
-  inline unsigned int get_size (void) const
-  {
-    return min_size + numPalettes * sizeof (HBUINT16);
-  }
+  unsigned int get_size () const
+  { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
 
-  inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
-  {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
+  unsigned int get_palette_count () const { return numPalettes; }
+  unsigned int get_color_count () const   { return numColors; }
 
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_flags (this, palette);
-  }
+  hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
+  { return v1 ().get_palette_flags (this, palette_index, numPalettes); }
 
-  inline unsigned int get_palette_name_id (unsigned int palette) const
-  {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return 0xFFFF;
+  hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
+  { return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
 
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_name_id (this, palette);
-  }
+  hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
+  { return v1 ().get_color_name_id (this, color_index, numColors); }
 
-  inline unsigned int get_palette_count () const
+  unsigned int get_palette_colors (unsigned int  palette_index,
+                                  unsigned int  start_offset,
+                                  unsigned int *color_count, /* IN/OUT.  May be NULL. */
+                                  hb_color_t   *colors       /* OUT.     May be NULL. */) const
   {
-    return numPalettes;
+    if (unlikely (palette_index >= numPalettes))
+    {
+      if (color_count) *color_count = 0;
+      return 0;
+    }
+    unsigned int start_index = colorRecordIndicesZ[palette_index];
+    hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
+    hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
+                                                                      numColors);
+    if (color_count)
+    {
+      hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count);
+      /* Always return numColors colors per palette even if it has out-of-bounds start index. */
+      unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count);
+      *color_count = count;
+      for (unsigned int i = 0; i < count; i++)
+        colors[i] = segment_colors[i]; /* Bound-checked read. */
+    }
+    return numColors;
   }
 
-  inline hb_ot_color_t
-  get_color_record_argb (unsigned int color_index, unsigned int palette) const
+  private:
+  const CPALV1Tail& v1 () const
   {
-    if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
-      return 0;
+    if (version == 0) return Null(CPALV1Tail);
+    return StructAfter<CPALV1Tail> (*this);
+  }
 
-    // No need for more range check as it is already done on #sanitize
-    const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
-    return color_records[colorRecordIndicesZ[palette] + color_index];
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 (this+colorRecordsZ).sanitize (c, numColorRecords) &&
+                 colorRecordIndicesZ.sanitize (c, numPalettes) &&
+                 (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
   }
 
   protected:
   HBUINT16     version;                /* Table version number */
   /* Version 0 */
-  HBUINT16     numPaletteEntries;      /* Number of palette entries in each palette. */
+  HBUINT16     numColors;              /* Number of colors in each palette. */
   HBUINT16     numPalettes;            /* Number of palettes in the table. */
   HBUINT16     numColorRecords;        /* Total number of color records, combined for
                                         * all palettes. */
-  LOffsetTo<UnsizedArrayOf<BGRAColor> >
+  LNNOffsetTo<UnsizedArrayOf<BGRAColor> >
                colorRecordsZ;          /* Offset from the beginning of CPAL table to
                                         * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>
index 09a9517..f6bdbb3 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SBIX_TABLE_HH
 #define HB_OT_COLOR_SBIX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * sbix -- Standard Bitmap Graphics
@@ -62,19 +62,65 @@ struct SBIXGlyph
 
 struct SBIXStrike
 {
-  friend struct sbix;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
+                 imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
   }
 
-  protected:
+  hb_blob_t *get_glyph_blob (unsigned int  glyph_id,
+                            hb_blob_t    *sbix_blob,
+                            hb_tag_t      file_type,
+                            int          *x_offset,
+                            int          *y_offset,
+                            unsigned int  num_glyphs,
+                            unsigned int *strike_ppem) const
+  {
+    if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
+
+    unsigned int retry_count = 8;
+    unsigned int sbix_len = sbix_blob->length;
+    unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
+    assert (strike_offset < sbix_len);
+
+  retry:
+    if (unlikely (glyph_id >= num_glyphs ||
+                 imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
+                 imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
+                 (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
+      return hb_blob_get_empty ();
+
+    unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
+    unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
+
+    const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
+
+    if (glyph->graphicType == HB_TAG ('d','u','p','e'))
+    {
+      if (glyph_length >= 2)
+      {
+       glyph_id = *((HBUINT16 *) &glyph->data);
+       if (retry_count--)
+         goto retry;
+      }
+      return hb_blob_get_empty ();
+    }
+
+    if (unlikely (file_type != glyph->graphicType))
+      return hb_blob_get_empty ();
+
+    if (strike_ppem) *strike_ppem = ppem;
+    if (x_offset) *x_offset = glyph->xOffset;
+    if (y_offset) *y_offset = glyph->yOffset;
+    return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
+  }
+
+  public:
   HBUINT16     ppem;           /* The PPEM size for which this strike was designed. */
   HBUINT16     resolution;     /* The device pixel density (in PPI) for which this
                                 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
+  protected:
   UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
                imageOffsetsZ;  /* Offset from the beginning of the strike data header
                                 * to bitmap data for an individual glyph ID. */
@@ -84,70 +130,157 @@ struct SBIXStrike
 
 struct sbix
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_sbix;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
-  }
+  bool has_data () const { return version; }
+
+  const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      num_glyphs = hb_face_get_glyph_count (face);
+      table = hb_sanitize_context_t().reference_table<sbix> (face);
+      num_glyphs = face->get_num_glyphs ();
+    }
+    void fini () { table.destroy (); }
+
+    bool has_data () const { return table->has_data (); }
 
-      OT::Sanitizer<OT::sbix> sanitizer;
-      sanitizer.set_num_glyphs (num_glyphs);
-      sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
-      sbix_len = hb_blob_get_length (sbix_blob);
-      sbix_table = sbix_blob->as<OT::sbix> ();
+    bool get_extents (hb_font_t          *font,
+                     hb_codepoint_t      glyph,
+                     hb_glyph_extents_t *extents) const
+    {
+      /* We only support PNG right now, and following function checks type. */
+      return get_png_extents (font, glyph, extents);
+    }
 
+    hb_blob_t *reference_png (hb_font_t      *font,
+                             hb_codepoint_t  glyph_id,
+                             int            *x_offset,
+                             int            *y_offset,
+                             unsigned int   *available_ppem) const
+    {
+      return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
+                                                 HB_TAG ('p','n','g',' '),
+                                                 x_offset, y_offset,
+                                                 num_glyphs, available_ppem);
     }
 
-    inline void fini (void)
+    private:
+
+    const SBIXStrike &choose_strike (hb_font_t *font) const
     {
-      hb_blob_destroy (sbix_blob);
+      unsigned count = table->strikes.len;
+      if (unlikely (!count))
+        return Null(SBIXStrike);
+
+      unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+      if (!requested_ppem)
+        requested_ppem = 1<<30; /* Choose largest strike. */
+      /* TODO Add DPI sensitivity as well? */
+      unsigned int best_i = 0;
+      unsigned int best_ppem = table->get_strike (0).ppem;
+
+      for (unsigned int i = 1; i < count; i++)
+      {
+       unsigned int ppem = (table->get_strike (i)).ppem;
+       if ((requested_ppem <= ppem && ppem < best_ppem) ||
+           (requested_ppem > best_ppem && ppem > best_ppem))
+       {
+         best_i = i;
+         best_ppem = ppem;
+       }
+      }
+
+      return table->get_strike (best_i);
     }
 
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-                                       unsigned int group, unsigned int gid)) const
+    struct PNGHeader
     {
-      for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
+      HBUINT8  signature[8];
+      struct
       {
-       const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
-       for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
-         if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
-         {
-           const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
-           callback ((const uint8_t*) &sbixGlyph.data,
-                     strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
-                     group, glyph);
-         }
+        struct
+       {
+         HBUINT32      length;
+         Tag           type;
+       }               header;
+       HBUINT32        width;
+       HBUINT32        height;
+       HBUINT8         bitDepth;
+       HBUINT8         colorType;
+       HBUINT8         compressionMethod;
+       HBUINT8         filterMethod;
+       HBUINT8         interlaceMethod;
+      } IHDR;
+
+      public:
+      DEFINE_SIZE_STATIC (29);
+    };
+
+    bool get_png_extents (hb_font_t          *font,
+                         hb_codepoint_t      glyph,
+                         hb_glyph_extents_t *extents) const
+    {
+      /* Following code is safe to call even without data.
+       * But faster to short-circuit. */
+      if (!has_data ())
+        return false;
+
+      int x_offset = 0, y_offset = 0;
+      unsigned int strike_ppem = 0;
+      hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
+
+      const PNGHeader &png = *blob->as<PNGHeader>();
+
+      extents->x_bearing = x_offset;
+      extents->y_bearing = y_offset;
+      extents->width     = png.IHDR.width;
+      extents->height    = png.IHDR.height;
+
+      /* Convert to font units. */
+      if (strike_ppem)
+      {
+       double scale = font->face->get_upem () / (double) strike_ppem;
+       extents->x_bearing = round (extents->x_bearing * scale);
+       extents->y_bearing = round (extents->y_bearing * scale);
+       extents->width = round (extents->width * scale);
+       extents->height = round (extents->height * scale);
       }
+
+      hb_blob_destroy (blob);
+
+      return strike_ppem;
     }
 
     private:
-    hb_blob_t *sbix_blob;
-    const sbix *sbix_table;
+    hb_blob_ptr_t<sbix> table;
 
-    unsigned int sbix_len;
     unsigned int num_glyphs;
-
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         version >= 1 &&
+                         strikes.sanitize (c, this)));
+  }
+
   protected:
   HBUINT16     version;        /* Table version number — set to 1 */
   HBUINT16     flags;          /* Bit 0: Set to 1. Bit 1: Draw outlines.
                                 * Bits 2 to 15: reserved (set to 0). */
-  LArrayOf<LOffsetTo<SBIXStrike> >
+  LOffsetLArrayOf<SBIXStrike>
                strikes;        /* Offsets from the beginning of the 'sbix'
                                 * table to data for each individual bitmap strike. */
   public:
   DEFINE_SIZE_ARRAY (8, strikes);
 };
 
+struct sbix_accelerator_t : sbix::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_SBIX_TABLE_HH */
index ed6cf97..6e8eddf 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SVG_TABLE_HH
 #define HB_OT_COLOR_SVG_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * SVG -- SVG (Scalable Vector Graphics)
@@ -40,13 +40,21 @@ namespace OT {
 
 struct SVGDocumentIndexEntry
 {
-  friend struct SVG;
+  int cmp (hb_codepoint_t g) const
+  { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void* base) const
+  hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
+  {
+    return hb_blob_create_sub_blob (svg_blob,
+                                   index_offset + (unsigned int) svgDoc,
+                                   svgDocLength);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 (base+svgDoc).sanitize (c, svgDocLength));
+                 svgDoc.sanitize (c, base, svgDocLength));
   }
 
   protected:
@@ -54,91 +62,62 @@ struct SVGDocumentIndexEntry
                                 * this index entry. */
   HBUINT16     endGlyphID;     /* The last glyph ID in the range described by
                                 * this index entry. Must be >= startGlyphID. */
-  LOffsetTo<UnsizedArrayOf<HBUINT8> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
                svgDoc;         /* Offset from the beginning of the SVG Document Index
                                 * to an SVG document. Must be non-zero. */
-  HBUINT32 svgDocLength;       /* Length of the SVG document.
+  HBUINT32     svgDocLength;   /* Length of the SVG document.
                                 * Must be non-zero. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
-struct SVGDocumentIndex
-{
-  friend struct SVG;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 entries.sanitize (c, this));
-  }
-
-  protected:
-  ArrayOf<SVGDocumentIndexEntry>
-               entries;        /* Array of SVG Document Index Entries. */
-  public:
-  DEFINE_SIZE_ARRAY (2, entries);
-};
-
 struct SVG
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_SVG;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                         (this+svgDocIndex).sanitize (c)));
-  }
+  bool has_data () const { return svgDocEntries; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
-    {
-      OT::Sanitizer<OT::SVG> sanitizer;
-      svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
-      svg_len = hb_blob_get_length (svg_blob);
-      svg = svg_blob->as<OT::SVG> ();
-
-    }
+    void init (hb_face_t *face)
+    { table = hb_sanitize_context_t().reference_table<SVG> (face); }
+    void fini () { table.destroy (); }
 
-    inline void fini (void)
+    hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
     {
-      hb_blob_destroy (svg_blob);
+      return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
+                                                              table->svgDocEntries);
     }
 
-    inline void
-    dump (void (*callback) (const uint8_t* data, unsigned int length,
-                           unsigned int start_glyph, unsigned int end_glyph)) const
-    {
-      const SVGDocumentIndex &index = svg+svg->svgDocIndex;
-      const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries;
-      for (unsigned int i = 0; i < entries.len; ++i)
-      {
-       const SVGDocumentIndexEntry &entry = entries[i];
-       callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength,
-                                                 entry.startGlyphID, entry.endGlyphID);
-      }
-    }
+    bool has_data () const { return table->has_data (); }
 
     private:
-    hb_blob_t *svg_blob;
-    const SVG *svg;
-
-    unsigned int svg_len;
+    hb_blob_ptr_t<SVG> table;
   };
 
+  const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
+  { return (this+svgDocEntries).bsearch (glyph_id); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         (this+svgDocEntries).sanitize_shallow (c)));
+  }
+
   protected:
   HBUINT16     version;        /* Table version (starting at 0). */
-  LOffsetTo<SVGDocumentIndex>
-               svgDocIndex;    /* Offset (relative to the start of the SVG table) to the
+  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> >
+               svgDocEntries;  /* Offset (relative to the start of the SVG table) to the
                                 * SVG Documents Index. Must be non-zero. */
+                               /* Array of SVG Document Index Entries. */
   HBUINT32     reserved;       /* Set to 0. */
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
+struct SVG_accelerator_t : SVG::accelerator_t {};
+
 } /* namespace OT */
 
 
index 86171c6..791135b 100644 (file)
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
- * Google Author(s): Sascha Brawer
+ * Google Author(s): Sascha Brawer, Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-color-cbdt-table.hh"
 #include "hb-ot-color-colr-table.hh"
 #include "hb-ot-color-cpal-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-face.hh"
 #include "hb-ot.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "hb-ot-layout-private.hh"
-#include "hb-shaper-private.hh"
+#include "hb-ot-layout.hh"
 
-#if 0
-HB_MARK_AS_FLAG_T (hb_ot_color_palette_flags_t)
-//HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) Hmm?
 
+/**
+ * SECTION:hb-ot-color
+ * @title: hb-ot-color
+ * @short_description: OpenType Color Fonts
+ * @include: hb-ot.h
+ *
+ * Functions for fetching color-font information from OpenType font faces.
+ **/
+
+
+/*
+ * CPAL
+ */
 
-static inline const OT::COLR&
-_get_colr (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::COLR);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->colr.get ());
-}
 
-static inline const OT::CPAL&
-_get_cpal (hb_face_t *face)
+/**
+ * hb_ot_color_has_palettes:
+ * @face: a font face.
+ *
+ * Returns: whether CPAL table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CPAL);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->cpal.get ());
+  return face->table.CPAL->has_data ();
 }
 
-
 /**
- * hb_ot_color_get_palette_count:
+ * hb_ot_color_palette_get_count:
  * @face: a font face.
  *
  * Returns: the number of color palettes in @face, or zero if @face has
  * no colors.
  *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 unsigned int
-hb_ot_color_get_palette_count (hb_face_t *face)
+hb_ot_color_palette_get_count (hb_face_t *face)
 {
-  const OT::CPAL& cpal = _get_cpal (face);
-  return cpal.get_palette_count ();
+  return face->table.CPAL->get_palette_count ();
 }
 
-
 /**
- * hb_ot_color_get_palette_name_id:
- * @face: a font face.
- * @palette: the index of the color palette whose name is being requested.
+ * hb_ot_color_palette_get_name_id:
+ * @face:    a font face.
+ * @palette_index: the index of the color palette whose name is being requested.
  *
  * Retrieves the name id of a color palette. For example, a color font can
  * have themed palettes like "Spring", "Summer", "Fall", and "Winter".
  *
  * Returns: an identifier within @face's `name` table.
- * If the requested palette has no name, or if @face has no colors,
- * or if @palette is not between 0 and hb_ot_color_get_palette_count(),
- * the result is 0xFFFF. The implementation does not check whether
- * the returned palette name id is actually in @face's `name` table.
+ * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
  *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
-unsigned int
-hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette)
+hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                unsigned int palette_index)
 {
-  const OT::CPAL& cpal = _get_cpal (face);
-  return cpal.get_palette_name_id (palette);
+  return face->table.CPAL->get_palette_name_id (palette_index);
 }
 
+/**
+ * hb_ot_color_palette_color_get_name_id:
+ * @face:        a font face.
+ * @color_index: palette entry index.
+ *
+ * Returns: Name ID associated with a palette entry, e.g. eye color
+ *
+ * Since: 2.1.0
+ */
+hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                      unsigned int color_index)
+{
+  return face->table.CPAL->get_color_name_id (color_index);
+}
 
 /**
- * hb_ot_color_get_palette_flags:
- * @face: a font face
- * @palette: the index of the color palette whose flags are being requested
+ * hb_ot_color_palette_get_flags:
+ * @face:          a font face
+ * @palette_index: the index of the color palette whose flags are being requested
  *
- * Returns: the flags for the requested color palette.  If @face has no colors,
- * or if @palette is not between 0 and hb_ot_color_get_palette_count(),
- * the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT.
+ * Returns: the flags for the requested color palette.
  *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 hb_ot_color_palette_flags_t
-hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                              unsigned int palette_index)
 {
-  const OT::CPAL& cpal = _get_cpal(face);
-  return cpal.get_palette_flags (palette);
+  return face->table.CPAL->get_palette_flags (palette_index);
 }
 
-
 /**
- * hb_ot_color_get_palette_colors:
+ * hb_ot_color_palette_get_colors:
  * @face:         a font face.
- * @palette:      the index of the color palette whose colors
+ * @palette_index:the index of the color palette whose colors
  *                are being requested.
  * @start_offset: the index of the first color being requested.
  * @color_count:  (inout) (optional): on input, how many colors
  *                can be maximally stored into the @colors array;
  *                on output, how many colors were actually stored.
- * @colors: (array length=color_count) (optional):
- *                an array of #hb_ot_color_t records. After calling
+ * @colors: (array length=color_count) (out) (optional):
+ *                an array of #hb_color_t records. After calling
  *                this function, @colors will be filled with
  *                the palette colors. If @colors is NULL, the function
  *                will just return the number of total colors
  *                without storing any actual colors; this can be used
  *                for allocating a buffer of suitable size before calling
- *                hb_ot_color_get_palette_colors() a second time.
+ *                hb_ot_color_palette_get_colors() a second time.
  *
  * Retrieves the colors in a color palette.
  *
- * Returns: the total number of colors in the palette. All palettes in
- * a font have the same number of colors. If @face has no colors, or if
- * @palette is not between 0 and hb_ot_color_get_palette_count(),
- * the result is zero.
+ * Returns: the total number of colors in the palette.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_palette_get_colors (hb_face_t     *face,
+                               unsigned int   palette_index,
+                               unsigned int   start_offset,
+                               unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
+                               hb_color_t    *colors        /* OUT.     May be NULL. */)
+{
+  return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
+}
+
+
+/*
+ * COLR
+ */
+
+/**
+ * hb_ot_color_has_layers:
+ * @face: a font face.
+ *
+ * Returns: whether COLR table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face)
+{
+  return face->table.COLR->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_get_layers:
+ * @face:         a font face.
+ * @glyph:        a layered color glyph id.
+ * @start_offset: starting offset of layers.
+ * @count:  (inout) (optional): gets number of layers available to be written on buffer
+ *                             and returns number of written layers.
+ * @layers: (array length=count) (out) (optional): layers buffer to buffer.
+ *
+ * Returns: Total number of layers a layered color glyph have.
  *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 unsigned int
-hb_ot_color_get_palette_colors (hb_face_t       *face,
-                               unsigned int     palette, /* default=0 */
-                               unsigned int     start_offset,
-                               unsigned int    *color_count /* IN/OUT */,
-                               hb_ot_color_t   *colors /* OUT */)
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                             hb_codepoint_t       glyph,
+                             unsigned int         start_offset,
+                             unsigned int        *count, /* IN/OUT.  May be NULL. */
+                             hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
 {
-  const OT::CPAL& cpal = _get_cpal(face);
-  if (unlikely (palette >= cpal.numPalettes))
-  {
-    if (color_count) *color_count = 0;
-    return 0;
-  }
-
-  const OT::ColorRecord* crec = &cpal.offsetFirstColorRecord (&cpal);
-  crec += cpal.colorRecordIndices[palette];
-
-  unsigned int num_results = 0;
-  if (likely (color_count && colors))
-  {
-    for (unsigned int i = start_offset;
-        i < cpal.numPaletteEntries && num_results < *color_count; ++i)
-    {
-      hb_ot_color_t* result = &colors[num_results];
-      result->red = crec[i].red;
-      result->green = crec[i].green;
-      result->blue = crec[i].blue;
-      result->alpha = crec[i].alpha;
-      ++num_results;
-    }
-  }
-
-  if (likely (color_count)) *color_count = num_results;
-  return cpal.numPaletteEntries;
+  return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers);
+}
+
+
+/*
+ * SVG
+ */
+
+/**
+ * hb_ot_color_has_svg:
+ * @face: a font face.
+ *
+ * Check whether @face has SVG glyph images.
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face)
+{
+  return face->table.SVG->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_svg:
+ * @face:  a font face.
+ * @glyph: a svg glyph index.
+ *
+ * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.
+ *
+ * Returns: (transfer full): respective svg blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
+{
+  return face->table.SVG->reference_blob_for_glyph (glyph);
+}
+
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+/**
+ * hb_ot_color_has_png:
+ * @face: a font face.
+ *
+ * Check whether @face has PNG glyph images (either CBDT or sbix tables).
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_png (hb_face_t *face)
+{
+  return face->table.CBDT->has_data () || face->table.sbix->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_png:
+ * @font:  a font object, not face. upem should be set on
+ *        that font object if one wants to get optimal png blob, otherwise
+ *        return the biggest one
+ * @glyph: a glyph index.
+ *
+ * Get PNG image for a glyph.
+ *
+ * Returns: (transfer full): respective PNG blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
+{
+  hb_blob_t *blob = hb_blob_get_empty ();
+
+  if (font->face->table.sbix->has_data ())
+    blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
+
+  if (!blob->length && font->face->table.CBDT->has_data ())
+    blob = font->face->table.CBDT->reference_png (font, glyph);
+
+  return blob;
 }
-#endif
diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h
new file mode 100644 (file)
index 0000000..49646bf
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ * Copyright © 2018  Khaled Hosny
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Sascha Brawer, Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_COLOR_H
+#define HB_OT_COLOR_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+HB_BEGIN_DECLS
+
+
+/*
+ * Color palettes.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_count (hb_face_t *face);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                unsigned int palette_index);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                      unsigned int color_index);
+
+/**
+ * hb_ot_color_palette_flags_t:
+ * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special
+ *   to note about a color palette.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a light background such as white.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a dark background such as black.
+ *
+ * Since: 2.1.0
+ */
+typedef enum { /*< flags >*/
+  HB_OT_COLOR_PALETTE_FLAG_DEFAULT                     = 0x00000000u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND        = 0x00000001u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND = 0x00000002u
+} hb_ot_color_palette_flags_t;
+
+HB_EXTERN hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                              unsigned int palette_index);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_colors (hb_face_t    *face,
+                               unsigned int  palette_index,
+                               unsigned int  start_offset,
+                               unsigned int *color_count,  /* IN/OUT.  May be NULL. */
+                               hb_color_t   *colors        /* OUT.     May be NULL. */);
+
+
+/*
+ * Color layers.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face);
+
+/**
+ * hb_ot_color_layer_t:
+ *
+ * Pairs of glyph and color index.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_color_layer_t
+{
+  hb_codepoint_t glyph;
+  unsigned int   color_index;
+} hb_ot_color_layer_t;
+
+HB_EXTERN unsigned int
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                             hb_codepoint_t       glyph,
+                             unsigned int         start_offset,
+                             unsigned int        *count, /* IN/OUT.  May be NULL. */
+                             hb_ot_color_layer_t *layers /* OUT.     May be NULL. */);
+
+/*
+ * SVG
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph);
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_png (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_COLOR_H */
diff --git a/src/hb-ot-deprecated.h b/src/hb-ot-deprecated.h
new file mode 100644 (file)
index 0000000..bce51b7
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_DEPRECATED_H
+#define HB_OT_DEPRECATED_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+
+HB_BEGIN_DECLS
+
+#ifndef HB_DISABLE_DEPRECATED
+
+
+/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
+hb_ot_layout_table_choose_script (hb_face_t      *face,
+                                 hb_tag_t        table_tag,
+                                 const hb_tag_t *script_tags,
+                                 unsigned int   *script_index,
+                                 hb_tag_t       *chosen_script);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
+hb_ot_layout_script_find_language (hb_face_t    *face,
+                                  hb_tag_t      table_tag,
+                                  unsigned int  script_index,
+                                  hb_tag_t      language_tag,
+                                  unsigned int *language_index);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
+hb_ot_tags_from_script (hb_script_t  script,
+                       hb_tag_t    *script_tag_1,
+                       hb_tag_t    *script_tag_2);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
+hb_ot_tag_from_language (hb_language_t language);
+
+
+/**
+ * HB_OT_VAR_NO_AXIS_INDEX:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+#define HB_OT_VAR_NO_AXIS_INDEX                0xFFFFFFFFu
+
+/**
+ * hb_ot_var_axis_t:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+typedef struct hb_ot_var_axis_t
+{
+  hb_tag_t tag;
+  hb_ot_name_id_t name_id;
+  float min_value;
+  float default_value;
+  float max_value;
+} hb_ot_var_axis_t;
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+hb_ot_var_get_axes (hb_face_t        *face,
+                   unsigned int      start_offset,
+                   unsigned int     *axes_count /* IN/OUT */,
+                   hb_ot_var_axis_t *axes_array /* OUT */);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+hb_ot_var_find_axis (hb_face_t        *face,
+                    hb_tag_t          axis_tag,
+                    unsigned int     *axis_index,
+                    hb_ot_var_axis_t *axis_info);
+
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_OT_DEPRECATED_H */
diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc
new file mode 100644 (file)
index 0000000..9b17526
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-face.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-name-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+void hb_ot_face_t::init0 (hb_face_t *face)
+{
+  this->face = face;
+#define HB_OT_TABLE(Namespace, Type) Type.init0 ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
+void hb_ot_face_t::fini ()
+{
+#define HB_OT_TABLE(Namespace, Type) Type.fini ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh
new file mode 100644 (file)
index 0000000..7f47ba6
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,2013  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
+ */
+
+#ifndef HB_OT_FACE_HH
+#define HB_OT_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-machinery.hh"
+
+
+/*
+ * hb_ot_face_t
+ */
+
+#define HB_OT_TABLES \
+    /* OpenType fundamentals. */ \
+    HB_OT_TABLE(OT, head) \
+    HB_OT_ACCELERATOR(OT, cmap) \
+    HB_OT_ACCELERATOR(OT, hmtx) \
+    HB_OT_ACCELERATOR(OT, vmtx) \
+    HB_OT_ACCELERATOR(OT, post) \
+    HB_OT_TABLE(OT, kern) \
+    HB_OT_ACCELERATOR(OT, glyf) \
+    HB_OT_ACCELERATOR(OT, cff1) \
+    HB_OT_ACCELERATOR(OT, cff2) \
+    HB_OT_TABLE(OT, VORG) \
+    HB_OT_ACCELERATOR(OT, name) \
+    HB_OT_TABLE(OT, OS2) \
+    HB_OT_TABLE(OT, STAT) \
+    /* OpenType shaping. */ \
+    HB_OT_ACCELERATOR(OT, GDEF) \
+    HB_OT_ACCELERATOR(OT, GSUB) \
+    HB_OT_ACCELERATOR(OT, GPOS) \
+    HB_OT_TABLE(OT, BASE) \
+    HB_OT_TABLE(OT, JSTF) \
+    /* AAT shaping. */ \
+    HB_OT_TABLE(AAT, mort) \
+    HB_OT_TABLE(AAT, morx) \
+    HB_OT_TABLE(AAT, kerx) \
+    HB_OT_TABLE(AAT, ankr) \
+    HB_OT_TABLE(AAT, trak) \
+    HB_OT_TABLE(AAT, lcar) \
+    HB_OT_TABLE(AAT, ltag) \
+    HB_OT_TABLE(AAT, feat) \
+    /* OpenType variations. */ \
+    HB_OT_TABLE(OT, fvar) \
+    HB_OT_TABLE(OT, avar) \
+    HB_OT_TABLE(OT, MVAR) \
+    /* OpenType math. */ \
+    HB_OT_TABLE(OT, MATH) \
+    /* OpenType color fonts. */ \
+    HB_OT_TABLE(OT, COLR) \
+    HB_OT_TABLE(OT, CPAL) \
+    HB_OT_ACCELERATOR(OT, CBDT) \
+    HB_OT_ACCELERATOR(OT, sbix) \
+    HB_OT_ACCELERATOR(OT, SVG) \
+    /* */
+
+/* Declare tables. */
+#define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
+HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+
+struct hb_ot_face_t
+{
+  HB_INTERNAL void init0 (hb_face_t *face);
+  HB_INTERNAL void fini ();
+
+#define HB_OT_TABLE_ORDER(Namespace, Type) \
+    HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
+  enum order_t
+  {
+    ORDER_ZERO,
+#define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+    HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+  };
+
+  hb_face_t *face; /* MUST be JUST before the lazy loaders. */
+#define HB_OT_TABLE(Namespace, Type) \
+  hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_ACCELERATOR(Namespace, Type) \
+  hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+};
+
+
+#endif /* HB_OT_FACE_HH */
index 8310230..20b09df 100644 (file)
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-ot.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-ot-face.hh"
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-kern-table.hh"
+#include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
-
+#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-vorg-table.hh"
 #include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-sbix-table.hh"
 
 
-struct hb_ot_font_t
-{
-  OT::cmap::accelerator_t cmap;
-  OT::hmtx::accelerator_t h_metrics;
-  OT::vmtx::accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
-  OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
-  OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
-};
-
-
-static hb_ot_font_t *
-_hb_ot_font_create (hb_face_t *face)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
-
-  if (unlikely (!ot_font))
-    return nullptr;
-
-  ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face);
-  ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
-  ot_font->glyf.init (face);
-  ot_font->cbdt.init (face);
-  ot_font->post.init (face);
-  ot_font->kern.init (face);
-
-  return ot_font;
-}
-
-static void
-_hb_ot_font_destroy (void *data)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
-
-  ot_font->cmap.fini ();
-  ot_font->h_metrics.fini ();
-  ot_font->v_metrics.fini ();
-  ot_font->glyf.fini ();
-  ot_font->cbdt.fini ();
-  ot_font->post.fini ();
-  ot_font->kern.fini ();
-
-  free (ot_font);
-}
+/**
+ * SECTION:hb-ot-font
+ * @title: hb-ot-font
+ * @short_description: OpenType font implementation
+ * @include: hb-ot.h
+ *
+ * Functions for using OpenType fonts with hb_shape().  Not that fonts returned
+ * by hb_font_create() default to using these functions, so most clients would
+ * never need to call these functions directly.
+ **/
 
 
 static hb_bool_t
@@ -93,10 +64,25 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
                         hb_codepoint_t unicode,
                         hb_codepoint_t *glyph,
                         void *user_data HB_UNUSED)
+{
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
+}
 
+static unsigned int
+hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                         void *font_data,
+                         unsigned int count,
+                         const hb_codepoint_t *first_unicode,
+                         unsigned int unicode_stride,
+                         hb_codepoint_t *first_glyph,
+                         unsigned int glyph_stride,
+                         void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyphs (count,
+                                           first_unicode, unicode_stride,
+                                           first_glyph, glyph_stride);
 }
 
 static hb_bool_t
@@ -107,39 +93,83 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
                           hb_codepoint_t *glyph,
                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_advance (hb_font_t *font,
-                          void *font_data,
-                          hb_codepoint_t glyph,
-                          void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                           unsigned count,
+                           const hb_codepoint_t *first_glyph,
+                           unsigned glyph_stride,
+                           hb_position_t *first_advance,
+                           unsigned advance_stride,
+                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_v_advance (hb_font_t *font,
-                          void *font_data,
-                          hb_codepoint_t glyph,
-                          void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+                           unsigned count,
+                           const hb_codepoint_t *first_glyph,
+                           unsigned glyph_stride,
+                           hb_position_t *first_advance,
+                           unsigned advance_stride,
+                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_kerning (hb_font_t *font,
-                          void *font_data,
-                          hb_codepoint_t left_glyph,
-                          hb_codepoint_t right_glyph,
-                          void *user_data HB_UNUSED)
+static hb_bool_t
+hb_ot_get_glyph_v_origin (hb_font_t *font,
+                         void *font_data,
+                         hb_codepoint_t glyph,
+                         hb_position_t *x,
+                         hb_position_t *y,
+                         void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+
+  *x = font->get_glyph_h_advance (glyph) / 2;
+
+  const OT::VORG &VORG = *ot_face->VORG;
+  if (VORG.has_data ())
+  {
+    *y = font->em_scale_y (VORG.get_y_origin (glyph));
+    return true;
+  }
+
+  hb_glyph_extents_t extents = {0};
+  if (ot_face->glyf->get_extents (glyph, &extents))
+  {
+    const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+    hb_position_t tsb = vmtx.get_side_bearing (glyph);
+    *y = font->em_scale_y (extents.y_bearing + tsb);
+    return true;
+  }
+
+  hb_font_extents_t font_extents;
+  font->get_h_extents_with_fallback (&font_extents);
+  *y = font_extents.ascender;
+
+  return true;
 }
 
 static hb_bool_t
@@ -149,10 +179,16 @@ hb_ot_get_glyph_extents (hb_font_t *font,
                         hb_glyph_extents_t *extents,
                         void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  bool ret = ot_font->glyf->get_extents (glyph, extents);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  bool ret = ot_face->sbix->get_extents (font, glyph, extents);
+  if (!ret)
+    ret = ot_face->glyf->get_extents (glyph, extents);
+  if (!ret)
+    ret = ot_face->cff1->get_extents (glyph, extents);
+  if (!ret)
+    ret = ot_face->cff2->get_extents (font, glyph, extents);
   if (!ret)
-    ret = ot_font->cbdt->get_extents (glyph, extents);
+    ret = ot_face->CBDT->get_extents (font, glyph, extents);
   // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
@@ -168,8 +204,8 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
                       char *name, unsigned int size,
                       void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_name (glyph, name, size);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_name (glyph, name, size);
 }
 
 static hb_bool_t
@@ -179,8 +215,8 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_from_name (name, len, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_from_name (name, len, glyph);
 }
 
 static hb_bool_t
@@ -189,12 +225,13 @@ hb_ot_get_font_h_extents (hb_font_t *font,
                          hb_font_extents_t *metrics,
                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
-  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
-  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+  metrics->ascender = font->em_scale_y (hmtx.ascender);
+  metrics->descender = font->em_scale_y (hmtx.descender);
+  metrics->line_gap = font->em_scale_y (hmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->h_metrics.has_font_extents;
+  return hmtx.has_font_extents;
 }
 
 static hb_bool_t
@@ -203,49 +240,34 @@ hb_ot_get_font_v_extents (hb_font_t *font,
                          hb_font_extents_t *metrics,
                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
-  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
-  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+  metrics->ascender = font->em_scale_x (vmtx.ascender);
+  metrics->descender = font->em_scale_x (vmtx.descender);
+  metrics->line_gap = font->em_scale_x (vmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->v_metrics.has_font_extents;
+  return vmtx.has_font_extents;
 }
 
-static hb_font_funcs_t *static_ot_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ot_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ot_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ot_funcs ();
 #endif
 
-static hb_font_funcs_t *
-_hb_ot_get_font_funcs (void)
+static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
@@ -253,17 +275,26 @@ retry:
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ot_funcs);
+#endif
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
+    return funcs;
+  }
+} static_ot_funcs;
+
+#if HB_USE_ATEXIT
+static
+void free_static_ot_funcs ()
+{
+  static_ot_funcs.free_instance ();
+}
 #endif
-  };
 
-  return funcs;
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs ()
+{
+  return static_ot_funcs.get_unconst ();
 }
 
 
@@ -275,12 +306,8 @@ retry:
 void
 hb_ot_font_set_funcs (hb_font_t *font)
 {
-  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
-  if (unlikely (!ot_font))
-    return;
-
   hb_font_set_funcs (font,
                     _hb_ot_get_font_funcs (),
-                    ot_font,
-                    _hb_ot_font_destroy);
+                    &font->face->table,
+                    nullptr);
 }
diff --git a/src/hb-ot-gasp-table.hh b/src/hb-ot-gasp-table.hh
new file mode 100644 (file)
index 0000000..94fff58
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_OT_GASP_TABLE_HH
+#define HB_OT_GASP_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-var-hvar-table.hh"
+
+/*
+ * gasp -- Grid-fitting and Scan-conversion Procedure
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gasp
+ */
+#define HB_OT_TAG_gasp HB_TAG('g','a','s','p')
+
+
+namespace OT {
+
+struct GaspRange
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16     rangeMaxPPEM;   /* Upper limit of range, in PPEM */
+  HBUINT16     rangeGaspBehavior;
+                               /* Flags describing desired rasterizer behavior. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct gasp
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_gasp;
+
+  const GaspRange &get_gasp_range (unsigned int i) const
+  { return gaspRanges[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 gaspRanges.sanitize (c));
+  }
+
+  protected:
+  HBUINT16     version;        /* Version number (set to 1) */
+  ArrayOf<GaspRange>
+               gaspRanges;     /* Number of records to follow
+                                * Sorted by ppem */
+  public:
+  DEFINE_SIZE_ARRAY (4, gaspRanges);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_GASP_TABLE_HH */
index 89c867d..c2b38b0 100644 (file)
 #ifndef HB_OT_GLYF_TABLE_HH
 #define HB_OT_GLYF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-subset-glyf.hh"
-#include "hb-subset-plan.hh"
-#include "hb-subset-private.hh"
 
 namespace OT {
 
@@ -47,17 +45,20 @@ struct loca
 {
   friend struct glyf;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_loca;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     return_trace (true);
   }
 
   protected:
-  HBUINT8              dataZ[VAR];             /* Location data. */
-  DEFINE_SIZE_ARRAY (0, dataZ);
+  UnsizedArrayOf<HBUINT8>      dataZ;          /* Location data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                       * check the size externally, allow Null() object of it by
+                       * defining it MIN() instead. */
 };
 
 
@@ -70,9 +71,9 @@ struct loca
 
 struct glyf
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -80,7 +81,7 @@ struct glyf
     return_trace (true);
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     hb_blob_t *glyf_prime = nullptr;
     hb_blob_t *loca_prime = nullptr;
@@ -103,14 +104,14 @@ struct glyf
   static bool
   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
   {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
+    hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
     hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
     hb_blob_destroy (head_blob);
 
     if (unlikely (!head_prime_blob))
       return false;
 
-    OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+    head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
     head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
     bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
 
@@ -121,9 +122,9 @@ struct glyf
   struct GlyphHeader
   {
     HBINT16            numberOfContours;       /* If the number of contours is
-                                                 * greater than or equal to zero,
-                                                 * this is a simple glyph; if negative,
-                                                 * this is a composite glyph. */
+                                                * greater than or equal to zero,
+                                                * this is a simple glyph; if negative,
+                                                * this is a composite glyph. */
     FWORD              xMin;                   /* Minimum x for coordinate data. */
     FWORD              yMin;                   /* Minimum y for coordinate data. */
     FWORD              xMax;                   /* Maximum x for coordinate data. */
@@ -150,28 +151,23 @@ struct glyf
     };
 
     HBUINT16 flags;
-    HBUINT16 glyphIndex;
+    GlyphID  glyphIndex;
 
-    inline unsigned int get_size (void) const
+    unsigned int get_size () const
     {
       unsigned int size = min_size;
-      if (flags & ARG_1_AND_2_ARE_WORDS) {
-        // arg1 and 2 are int16
-        size += 4;
-      } else {
-        // arg1 and 2 are int8
-        size += 2;
-      }
-      if (flags & WE_HAVE_A_SCALE) {
-        // One x 16 bit (scale)
-        size += 2;
-      } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
-        // Two x 16 bit (xscale, yscale)
-        size += 4;
-      } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
-        // Four x 16 bit (xscale, scale01, scale10, yscale)
-        size += 8;
-      }
+      // arg1 and 2 are int16
+      if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+      // arg1 and 2 are int8
+      else size += 2;
+
+      // One x 16 bit (scale)
+      if (flags & WE_HAVE_A_SCALE) size += 2;
+      // Two x 16 bit (xscale, yscale)
+      else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+      // Four x 16 bit (xscale, scale01, scale10, yscale)
+      else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
       return size;
     }
 
@@ -181,7 +177,7 @@ struct glyf
       const char *glyph_end;
       const CompositeGlyphHeader *current;
 
-      inline bool move_to_next ()
+      bool move_to_next ()
       {
        if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
        {
@@ -195,17 +191,17 @@ struct glyf
        return false;
       }
 
-      inline bool in_range (const CompositeGlyphHeader *composite) const
+      bool in_range (const CompositeGlyphHeader *composite) const
       {
        return (const char *) composite >= glyph_start
          && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
-         && ((const char *) composite + composite->get_size()) <= glyph_end;
+         && ((const char *) composite + composite->get_size ()) <= glyph_end;
       }
     };
 
-    static inline bool get_iterator (const char * glyph_data,
-                                    unsigned int length,
-                                    CompositeGlyphHeader::Iterator *iterator /* OUT */)
+    static bool get_iterator (const char * glyph_data,
+                             unsigned int length,
+                             CompositeGlyphHeader::Iterator *iterator /* OUT */)
     {
       if (length < GlyphHeader::static_size)
        return false; /* Empty glyph; zero extents. */
@@ -213,15 +209,15 @@ struct glyf
       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph_data, 0);
       if (glyph_header.numberOfContours < 0)
       {
-        const CompositeGlyphHeader *possible =
+       const CompositeGlyphHeader *possible =
          &StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header);
 
        iterator->glyph_start = glyph_data;
        iterator->glyph_end = (const char *) glyph_data + length;
        if (!iterator->in_range (possible))
-          return false;
-        iterator->current = possible;
-        return true;
+         return false;
+       iterator->current = possible;
+       return true;
       }
 
       return false;
@@ -232,34 +228,26 @@ struct glyf
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       memset (this, 0, sizeof (accelerator_t));
 
-      hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
-      const head *head_table = head_blob->as<head> ();
-      if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
-      {
-       /* head table is not present, or in an unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-       hb_blob_destroy (head_blob);
+      const OT::head &head = *face->table.head;
+      if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0)
+       /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
        return;
-      }
-      short_offset = 0 == head_table->indexToLocFormat;
-      hb_blob_destroy (head_blob);
+      short_offset = 0 == head.indexToLocFormat;
 
-      loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
-      loca_table = loca_blob->as<loca> ();
-      glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
-      glyf_table = glyf_blob->as<glyf> ();
+      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
 
-      num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
-      glyf_len = hb_blob_get_length (glyf_blob);
+      num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (loca_blob);
-      hb_blob_destroy (glyf_blob);
+      loca_table.destroy ();
+      glyf_table.destroy ();
     }
 
     /*
@@ -267,35 +255,37 @@ struct glyf
      * If true is returned a pointer to the composite glyph will be written into
      * composite.
      */
-    inline bool get_composite (hb_codepoint_t glyph,
-                              CompositeGlyphHeader::Iterator *composite /* OUT */) const
+    bool get_composite (hb_codepoint_t glyph,
+                       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
-      if (this->glyf_table == &Null(glyf) || !num_glyphs)
+      if (unlikely (!num_glyphs))
        return false;
 
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
-        return false; /* glyph not found */
+       return false; /* glyph not found */
 
-      return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
+      return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset,
                                                 end_offset - start_offset,
                                                 composite);
     }
 
     enum simple_glyph_flag_t {
+      FLAG_ON_CURVE = 0x01,
       FLAG_X_SHORT = 0x02,
       FLAG_Y_SHORT = 0x04,
       FLAG_REPEAT = 0x08,
       FLAG_X_SAME = 0x10,
-      FLAG_Y_SAME = 0x20
+      FLAG_Y_SAME = 0x20,
+      FLAG_RESERVED1 = 0x40,
+      FLAG_RESERVED2 = 0x80
     };
 
     /* based on FontTools _g_l_y_f.py::trim */
-    inline bool remove_padding(unsigned int start_offset,
-                               unsigned int *end_offset) const
+    bool remove_padding (unsigned int start_offset,
+                               unsigned int *end_offset) const
     {
-      if (*end_offset - start_offset < GlyphHeader::static_size)
-        return true;
+      if (*end_offset - start_offset < GlyphHeader::static_size) return true;
 
       const char *glyph = ((const char *) glyf_table) + start_offset;
       const char * const glyph_end = glyph + (*end_offset - start_offset);
@@ -303,143 +293,139 @@ struct glyf
       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
 
       if (num_contours < 0)
-        /* Trimming for composites not implemented.
-         * If removing hints it falls out of that. */
-        return true;
+       /* Trimming for composites not implemented.
+        * If removing hints it falls out of that. */
+       return true;
       else if (num_contours > 0)
       {
-        /* simple glyph w/contours, possibly trimmable */
-        glyph += GlyphHeader::static_size + 2 * num_contours;
-
-        if (unlikely (glyph + 2 >= glyph_end)) return false;
-        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
-        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
-
-        glyph += 2 + nInstructions;
-        if (unlikely (glyph + 2 >= glyph_end)) return false;
-
-        unsigned int coordBytes = 0;
-        unsigned int coordsWithFlags = 0;
-        while (glyph < glyph_end)
-        {
-          uint8_t flag = (uint8_t) *glyph;
-          glyph++;
-
-          unsigned int repeat = 1;
-          if (flag & FLAG_REPEAT)
-          {
-            if (glyph >= glyph_end)
-            {
-              DEBUG_MSG(SUBSET, nullptr, "Bad flag");
-              return false;
-            }
-            repeat = ((uint8_t) *glyph) + 1;
-            glyph++;
-          }
-
-          unsigned int xBytes, yBytes;
-          xBytes = yBytes = 0;
-          if (flag & FLAG_X_SHORT)
-            xBytes = 1;
-          else if ((flag & FLAG_X_SAME) == 0)
-            xBytes = 2;
-
-          if (flag & FLAG_Y_SHORT)
-            yBytes = 1;
-          else if ((flag & FLAG_Y_SAME) == 0)
-            yBytes = 2;
-
-          coordBytes += (xBytes + yBytes) * repeat;
-          coordsWithFlags += repeat;
-          if (coordsWithFlags >= nCoordinates)
-            break;
-        }
-
-        if (coordsWithFlags != nCoordinates)
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
-          return false;
-        }
-        glyph += coordBytes;
-
-        if (glyph < glyph_end)
-          *end_offset -= glyph_end - glyph;
+       /* simple glyph w/contours, possibly trimmable */
+       glyph += GlyphHeader::static_size + 2 * num_contours;
+
+       if (unlikely (glyph + 2 >= glyph_end)) return false;
+       uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+       uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16> (glyph, 0);
+
+       glyph += 2 + nInstructions;
+       if (unlikely (glyph + 2 >= glyph_end)) return false;
+
+       unsigned int coordBytes = 0;
+       unsigned int coordsWithFlags = 0;
+       while (glyph < glyph_end)
+       {
+         uint8_t flag = (uint8_t) *glyph;
+         glyph++;
+
+         unsigned int repeat = 1;
+         if (flag & FLAG_REPEAT)
+         {
+           if (glyph >= glyph_end)
+           {
+             DEBUG_MSG(SUBSET, nullptr, "Bad flag");
+             return false;
+           }
+           repeat = ((uint8_t) *glyph) + 1;
+           glyph++;
+         }
+
+         unsigned int xBytes, yBytes;
+         xBytes = yBytes = 0;
+         if (flag & FLAG_X_SHORT) xBytes = 1;
+         else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
+
+         if (flag & FLAG_Y_SHORT) yBytes = 1;
+         else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
+
+         coordBytes += (xBytes + yBytes) * repeat;
+         coordsWithFlags += repeat;
+         if (coordsWithFlags >= nCoordinates)
+           break;
+       }
+
+       if (coordsWithFlags != nCoordinates)
+       {
+         DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
+         return false;
+       }
+       glyph += coordBytes;
+
+       if (glyph < glyph_end)
+         *end_offset -= glyph_end - glyph;
       }
       return true;
     }
 
-    inline bool get_offsets (hb_codepoint_t  glyph,
-                             unsigned int   *start_offset /* OUT */,
-                             unsigned int   *end_offset   /* OUT */) const
+    bool get_offsets (hb_codepoint_t  glyph,
+                     unsigned int   *start_offset /* OUT */,
+                     unsigned int   *end_offset   /* OUT */) const
     {
       if (unlikely (glyph >= num_glyphs))
        return false;
 
       if (short_offset)
       {
-        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ;
+       const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
        *start_offset = 2 * offsets[glyph];
        *end_offset   = 2 * offsets[glyph + 1];
       }
       else
       {
-        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ;
+       const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
 
        *start_offset = offsets[glyph];
        *end_offset   = offsets[glyph + 1];
       }
 
-      if (*start_offset > *end_offset || *end_offset > glyf_len)
+      if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ())
        return false;
 
       return true;
     }
 
-    inline bool get_instruction_offsets(unsigned int start_offset,
-                                        unsigned int end_offset,
-                                        unsigned int *instruction_start /* OUT */,
-                                        unsigned int *instruction_end /* OUT */) const
+    bool get_instruction_offsets (unsigned int start_offset,
+                                 unsigned int end_offset,
+                                 unsigned int *instruction_start /* OUT */,
+                                 unsigned int *instruction_end /* OUT */) const
     {
       if (end_offset - start_offset < GlyphHeader::static_size)
       {
-        *instruction_start = 0;
-        *instruction_end = 0;
-        return true; /* Empty glyph; no instructions. */
+       *instruction_start = 0;
+       *instruction_end = 0;
+       return true; /* Empty glyph; no instructions. */
       }
       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
       if (num_contours < 0)
       {
-        CompositeGlyphHeader::Iterator composite_it;
-        if (unlikely (!CompositeGlyphHeader::get_iterator (
-            (const char*) this->glyf_table + start_offset,
-             end_offset - start_offset, &composite_it))) return false;
-        const CompositeGlyphHeader *last;
-        do {
-          last = composite_it.current;
-        } while (composite_it.move_to_next());
-
-        if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-          *instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size();
-        else
-          *instruction_start = end_offset;
-        *instruction_end = end_offset;
-        if (unlikely (*instruction_start > *instruction_end))
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
-          return false;
-        }
+       CompositeGlyphHeader::Iterator composite_it;
+       if (unlikely (!CompositeGlyphHeader::get_iterator (
+           (const char*) this->glyf_table + start_offset,
+            end_offset - start_offset, &composite_it))) return false;
+       const CompositeGlyphHeader *last;
+       do {
+         last = composite_it.current;
+       } while (composite_it.move_to_next ());
+
+       if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
+         *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
+       else
+         *instruction_start = end_offset;
+       *instruction_end = end_offset;
+       if (unlikely (*instruction_start > *instruction_end))
+       {
+         DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
+         return false;
+       }
       }
       else
       {
-        unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
+       unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
        if (unlikely (instruction_length_offset + 2 > end_offset))
        {
          DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
          return false;
        }
 
-        const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
+       const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
        unsigned int start = instruction_length_offset + 2;
        unsigned int end = start + (uint16_t) instruction_length;
        if (unlikely (end > end_offset)) // Out of bounds of the current glyph
@@ -449,17 +435,16 @@ struct glyf
        }
 
        *instruction_start = start;
-        *instruction_end = end;
+       *instruction_end = end;
       }
       return true;
     }
 
-    inline bool get_extents (hb_codepoint_t glyph,
-                            hb_glyph_extents_t *extents) const
+    bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
     {
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
-        return false;
+       return false;
 
       if (end_offset - start_offset < GlyphHeader::static_size)
        return true; /* Empty glyph; zero extents. */
@@ -477,19 +462,20 @@ struct glyf
     private:
     bool short_offset;
     unsigned int num_glyphs;
-    const loca *loca_table;
-    const glyf *glyf_table;
-    hb_blob_t *loca_blob;
-    hb_blob_t *glyf_blob;
-    unsigned int glyf_len;
+    hb_blob_ptr_t<loca> loca_table;
+    hb_blob_ptr_t<glyf> glyf_table;
   };
 
   protected:
-  HBUINT8              dataZ[VAR];             /* Glyphs data. */
-
-  DEFINE_SIZE_ARRAY (0, dataZ);
+  UnsizedArrayOf<HBUINT8>      dataZ;          /* Glyphs data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                       * check the size externally, allow Null() object of it by
+                       * defining it MIN() instead. */
 };
 
+struct glyf_accelerator_t : glyf::accelerator_t {};
+
 } /* namespace OT */
 
 
index d406e3e..95229c5 100644 (file)
@@ -27,8 +27,7 @@
 #ifndef HB_OT_HDMX_TABLE_HH
 #define HB_OT_HDMX_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 /*
  * hdmx -- Horizontal Device Metrics
@@ -45,57 +44,51 @@ struct DeviceRecord
   struct SubsetView
   {
     const DeviceRecord *source_device_record;
-    unsigned int size_device_record;
+    unsigned int sizeDeviceRecord;
     hb_subset_plan_t *subset_plan;
 
-    inline void init(const DeviceRecord *source_device_record,
-                    unsigned int size_device_record,
-                    hb_subset_plan_t   *subset_plan)
+    void init (const DeviceRecord *source_device_record,
+              unsigned int sizeDeviceRecord,
+              hb_subset_plan_t   *subset_plan)
     {
       this->source_device_record = source_device_record;
-      this->size_device_record = size_device_record;
+      this->sizeDeviceRecord = sizeDeviceRecord;
       this->subset_plan = subset_plan;
     }
 
-    inline unsigned int len () const
-    {
-      return this->subset_plan->glyphs.len;
-    }
+    unsigned int len () const
+    { return this->subset_plan->glyphs.length; }
 
-    inline const HBUINT8* operator [] (unsigned int i) const
+    const HBUINT8* operator [] (unsigned int i) const
     {
-      if (unlikely (i >= len())) return nullptr;
+      if (unlikely (i >= len ())) return nullptr;
       hb_codepoint_t gid = this->subset_plan->glyphs [i];
 
-      const HBUINT8* width = &(this->source_device_record->widths[gid]);
-
-      if (width < ((const HBUINT8 *) this->source_device_record) + size_device_record)
-       return width;
-      else
-       return nullptr;
+      if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
+        return nullptr;
+      return &(this->source_device_record->widthsZ[gid]);
     }
   };
 
-  static inline unsigned int get_size (unsigned int count)
-  {
-    unsigned int raw_size = min_size + count * HBUINT8::static_size;
-    if (raw_size % 4)
-      /* Align to 32 bits */
-      return raw_size + (4 - (raw_size % 4));
-    return raw_size;
-  }
+  static unsigned int get_size (unsigned int count)
+  { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
 
-  inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
   {
     TRACE_SERIALIZE (this);
 
-    if (unlikely (!c->allocate_size<DeviceRecord> (get_size (subset_view.len()))))
+    unsigned int size = get_size (subset_view.len ());
+    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
+                size);
       return_trace (false);
+    }
 
-    this->pixel_size.set (subset_view.source_device_record->pixel_size);
-    this->max_width.set (subset_view.source_device_record->max_width);
+    this->pixelSize.set (subset_view.source_device_record->pixelSize);
+    this->maxWidth.set (subset_view.source_device_record->maxWidth);
 
-    for (unsigned int i = 0; i < subset_view.len(); i++)
+    for (unsigned int i = 0; i < subset_view.len (); i++)
     {
       const HBUINT8 *width = subset_view[i];
       if (!width)
@@ -103,56 +96,56 @@ struct DeviceRecord
        DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
        return_trace (false);
       }
-      widths[i].set (*width);
+      widthsZ[i].set (*width);
     }
 
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                         c->check_range (this, size_device_record)));
+                         c->check_range (this, sizeDeviceRecord)));
   }
 
-  HBUINT8 pixel_size;   /* Pixel size for following widths (as ppem). */
-  HBUINT8 max_width;    /* Maximum width. */
-  HBUINT8 widths[VAR];  /* Array of widths (numGlyphs is from the 'maxp' table). */
+  HBUINT8                      pixelSize;      /* Pixel size for following widths (as ppem). */
+  HBUINT8                      maxWidth;       /* Maximum width. */
+  UnsizedArrayOf<HBUINT8>      widthsZ;        /* Array of widths (numGlyphs is from the 'maxp' table). */
   public:
-  DEFINE_SIZE_ARRAY (2, widths);
+  DEFINE_SIZE_ARRAY (2, widthsZ);
 };
 
 
 struct hdmx
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_hdmx;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hdmx;
 
-  inline unsigned int get_size (void) const
-  {
-    return min_size + num_records * size_device_record;
-  }
+  unsigned int get_size () const
+  { return min_size + numRecords * sizeDeviceRecord; }
 
-  inline const DeviceRecord& operator [] (unsigned int i) const
+  const DeviceRecord& operator [] (unsigned int i) const
   {
-    if (unlikely (i >= num_records)) return Null(DeviceRecord);
-    return StructAtOffset<DeviceRecord> (this->data, i * size_device_record);
+    /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
+     * https://github.com/harfbuzz/harfbuzz/issues/1300 */
+    if (unlikely (i >= numRecords)) return Null (DeviceRecord);
+    return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
   }
 
-  inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
     this->version.set (source_hdmx->version);
-    this->num_records.set (source_hdmx->num_records);
-    this->size_device_record.set (DeviceRecord::get_size (plan->glyphs.len));
+    this->numRecords.set (source_hdmx->numRecords);
+    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
 
-    for (unsigned int i = 0; i < source_hdmx->num_records; i++)
+    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
     {
       DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], source_hdmx->size_device_record, plan);
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
 
       if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
        return_trace (false);
@@ -161,14 +154,14 @@ struct hdmx
     return_trace (true);
   }
 
-  static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
+  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
   {
-    return min_size + DeviceRecord::get_size (plan->glyphs.len);
+    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
-    size_t dest_size = get_subsetted_size (plan);
+    size_t dest_size = get_subsetted_size (this, plan);
     hdmx *dest = (hdmx *) malloc (dest_size);
     if (unlikely (!dest))
     {
@@ -178,8 +171,10 @@ struct hdmx
 
     hb_serialize_context_t c (dest, dest_size);
     hdmx *hdmx_prime = c.start_serialize<hdmx> ();
-    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) {
+    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
+    {
       free (dest);
+      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
       return false;
     }
     c.end_serialize ();
@@ -195,22 +190,22 @@ struct hdmx
     return result;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && version == 0 &&
-                 !_hb_unsigned_int_mul_overflows (num_records, size_device_record) &&
-                 size_device_record >= DeviceRecord::min_size &&
-                 c->check_range (this, get_size()));
+    return_trace (c->check_struct (this) &&
+                 !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+                 sizeDeviceRecord >= DeviceRecord::min_size &&
+                 c->check_range (this, get_size ()));
   }
 
   protected:
-  HBUINT16     version;                /* Table version number (0) */
-  HBUINT16     num_records;            /* Number of device records. */
-  HBUINT32     size_device_record;     /* Size of a device record, 32-bit aligned. */
-  HBUINT8      data[VAR];              /* Array of device records. */
+  HBUINT16             version;                /* Table version number (0) */
+  HBUINT16             numRecords;             /* Number of device records. */
+  HBUINT32             sizeDeviceRecord;       /* Size of a device record, 32-bit aligned. */
+  DeviceRecord         firstDeviceRecord;      /* Array of device records. */
   public:
-  DEFINE_SIZE_ARRAY (8, data);
+  DEFINE_SIZE_MIN (8);
 };
 
 } /* namespace OT */
index 965e30a..3c0bb3d 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_OT_HEAD_TABLE_HH
 #define HB_OT_HEAD_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * head -- Font Header
@@ -45,16 +45,29 @@ struct head
 {
   friend struct OffsetTable;
 
-  static const hb_tag_t tableTag       = HB_OT_TAG_head;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_head;
 
-  inline unsigned int get_upem (void) const
+  unsigned int get_upem () const
   {
     unsigned int upem = unitsPerEm;
     /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum mac_style_flag_t {
+    BOLD       = 1u<<0,
+    ITALIC     = 1u<<1,
+    UNDERLINE  = 1u<<2,
+    OUTLINE    = 1u<<3,
+    SHADOW     = 1u<<4,
+    CONDENSED  = 1u<<5
+  };
+
+  bool is_bold () const      { return macStyle & BOLD; }
+  bool is_italic () const    { return macStyle & ITALIC; }
+  bool is_condensed () const { return macStyle & CONDENSED; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -141,8 +154,8 @@ struct head
                                         * -1: Only strongly right to left;
                                         * -2: Like -1 but also contains neutrals. */
   public:
-  HBINT16      indexToLocFormat;       /* 0 for short offsets, 1 for long. */
-  HBINT16      glyphDataFormat;        /* 0 for current format. */
+  HBUINT16     indexToLocFormat;       /* 0 for short offsets, 1 for long. */
+  HBUINT16     glyphDataFormat;        /* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
index efb42b6..c3155b7 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_HHEA_TABLE_HH
 #define HB_OT_HHEA_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * hhea -- Horizontal Header
@@ -45,7 +45,7 @@ namespace OT {
 template <typename T>
 struct _hea
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && likely (version.major == 1));
@@ -86,10 +86,10 @@ struct _hea
 };
 
 struct hhea : _hea<hhea> {
-  static const hb_tag_t tableTag       = HB_OT_TAG_hhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hhea;
 };
 struct vhea : _hea<vhea> {
-  static const hb_tag_t tableTag       = HB_OT_TAG_vhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vhea;
 };
 
 
index 2c62664..a95a56f 100644 (file)
 #ifndef HB_OT_HMTX_TABLE_HH
 #define HB_OT_HMTX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-os2-table.hh"
 #include "hb-ot-var-hvar-table.hh"
-#include "hb-subset-plan.hh"
 
 /*
  * hmtx -- Horizontal Metrics
@@ -49,7 +48,7 @@ namespace OT {
 struct LongMetric
 {
   UFWORD       advance; /* Advance width/height. */
-  FWORD                lsb; /* Leading (left/top) side bearing. */
+  FWORD                sb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -57,7 +56,7 @@ struct LongMetric
 template <typename T, typename H>
 struct hmtxvmtx
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -66,11 +65,11 @@ struct hmtxvmtx
   }
 
 
-  inline bool subset_update_header (hb_subset_plan_t *plan,
-                                    unsigned int num_hmetrics) const
+  bool subset_update_header (hb_subset_plan_t *plan,
+                                   unsigned int num_hmetrics) const
   {
-    hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
-    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
+    hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
+    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
     hb_blob_destroy (src_blob);
 
     if (unlikely (!dest_blob)) {
@@ -87,7 +86,7 @@ struct hmtxvmtx
     return result;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     typename T::accelerator_t _mtx;
     _mtx.init (plan->source);
@@ -95,33 +94,33 @@ struct hmtxvmtx
     /* All the trailing glyphs with the same advance can use one LongMetric
      * and just keep LSB */
     hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
-    unsigned int num_advances = gids.len;
+    unsigned int num_advances = gids.length;
     unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
-    while (num_advances > 1
-        && last_advance == _mtx.get_advance (gids[num_advances - 2]))
+    while (num_advances > 1 &&
+          last_advance == _mtx.get_advance (gids[num_advances - 2]))
     {
       num_advances--;
     }
 
     /* alloc the new table */
     size_t dest_sz = num_advances * 4
-                  + (gids.len - num_advances) * 2;
+                 + (gids.length - num_advances) * 2;
     void *dest = (void *) malloc (dest_sz);
     if (unlikely (!dest))
     {
       return false;
     }
     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz);
+    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz);
 
-    const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
+    const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
     // Copy everything over
     LongMetric * old_metrics = (LongMetric *) source_table;
     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
     char * dest_pos = (char *) dest;
 
     bool failed = false;
-    for (unsigned int i = 0; i < gids.len; i++)
+    for (unsigned int i = 0; i < gids.length; i++)
     {
       /* the last metric or the one for gids[i] */
       LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
@@ -135,8 +134,8 @@ struct hmtxvmtx
         }
         else
         {
-          /* dest just lsb */
-          *((FWORD *) dest_pos) = src_metric->lsb;
+          /* dest just sb */
+          *((FWORD *) dest_pos) = src_metric->sb;
         }
       }
       else
@@ -148,18 +147,18 @@ struct hmtxvmtx
          failed = true;
          break;
        }
-       FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
+       FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
         if (i < num_advances)
         {
           /* dest needs a full LongMetric */
           LongMetric *metric = (LongMetric *)dest_pos;
           metric->advance = src_metric->advance;
-          metric->lsb = src_lsb;
+          metric->sb = src_sb;
         }
         else
         {
-          /* dest just needs an lsb */
-          *((FWORD *) dest_pos) = src_lsb;
+          /* dest just needs an sb */
+          *((FWORD *) dest_pos) = src_sb;
         }
       }
       dest_pos += (i < num_advances ? 4 : 2);
@@ -187,34 +186,27 @@ struct hmtxvmtx
   {
     friend struct hmtxvmtx;
 
-    inline void init (hb_face_t *face,
+    void init (hb_face_t *face,
                      unsigned int default_advance_ = 0)
     {
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
 
       bool got_font_extents = false;
-      if (T::os2Tag)
+      if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
       {
-       hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
-       const os2 *os2_table = os2_blob->as<os2> ();
-#define USE_TYPO_METRICS (1u<<7)
-       if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
-       {
-         ascender = os2_table->sTypoAscender;
-         descender = os2_table->sTypoDescender;
-         line_gap = os2_table->sTypoLineGap;
-         got_font_extents = (ascender | descender) != 0;
-       }
-       hb_blob_destroy (os2_blob);
+       ascender = abs (face->table.OS2->sTypoAscender);
+       descender = -abs (face->table.OS2->sTypoDescender);
+       line_gap = face->table.OS2->sTypoLineGap;
+       got_font_extents = (ascender | descender) != 0;
       }
 
-      hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
+      hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
       const H *_hea_table = _hea_blob->as<H> ();
       num_advances = _hea_table->numberOfLongMetrics;
       if (!got_font_extents)
       {
-       ascender = _hea_table->ascender;
-       descender = _hea_table->descender;
+       ascender = abs (_hea_table->ascender);
+       descender = -abs (_hea_table->descender);
        line_gap = _hea_table->lineGap;
        got_font_extents = (ascender | descender) != 0;
       }
@@ -222,10 +214,10 @@ struct hmtxvmtx
 
       has_font_extents = got_font_extents;
 
-      blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
+      table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
 
       /* Cap num_metrics() and num_advances() based on table length. */
-      unsigned int len = hb_blob_get_length (blob);
+      unsigned int len = table.get_length ();
       if (unlikely (num_advances * 4 > len))
        num_advances = len / 4;
       num_metrics = num_advances + (len - 4 * num_advances) / 2;
@@ -235,53 +227,64 @@ struct hmtxvmtx
       if (unlikely (!num_advances))
       {
        num_metrics = num_advances = 0;
-       hb_blob_destroy (blob);
-       blob = hb_blob_get_empty ();
+       table.destroy ();
+       table = hb_blob_get_empty ();
       }
-      table = blob->as<hmtxvmtx> ();
 
-      var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
-      var_table = var_blob->as<HVARVVAR> ();
+      var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (blob);
-      hb_blob_destroy (var_blob);
+      table.destroy ();
+      var_table.destroy ();
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph) const
+    /* TODO Add variations version. */
+    unsigned int get_side_bearing (hb_codepoint_t glyph) const
+    {
+      if (glyph < num_advances)
+        return table->longMetricZ[glyph].sb;
+
+      if (unlikely (glyph >= num_metrics))
+        return 0;
+
+      const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
+      return bearings[glyph - num_advances];
+    }
+
+    unsigned int get_advance (hb_codepoint_t glyph) const
     {
       if (unlikely (glyph >= num_metrics))
       {
-        /* If num_metrics is zero, it means we don't have the metrics table
-         * for this direction: return default advance.  Otherwise, it means that the
-         * glyph index is out of bound: return zero. */
-        if (num_metrics)
-          return 0;
-        else
-          return default_advance;
+       /* If num_metrics is zero, it means we don't have the metrics table
+        * for this direction: return default advance.  Otherwise, it means that the
+        * glyph index is out of bound: return zero. */
+       if (num_metrics)
+         return 0;
+       else
+         return default_advance;
       }
 
-      return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
+      return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph,
-                                     hb_font_t      *font) const
+    unsigned int get_advance (hb_codepoint_t  glyph,
+                             hb_font_t      *font) const
     {
       unsigned int advance = get_advance (glyph);
-      if (likely(glyph < num_metrics))
+      if (likely (glyph < num_metrics))
       {
-        advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
+       advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
       }
       return advance;
     }
 
     public:
     bool has_font_extents;
-    unsigned short ascender;
-    unsigned short descender;
-    unsigned short line_gap;
+    int ascender;
+    int descender;
+    int line_gap;
 
     protected:
     unsigned int num_metrics;
@@ -289,14 +292,12 @@ struct hmtxvmtx
     unsigned int default_advance;
 
     private:
-    const hmtxvmtx *table;
-    hb_blob_t *blob;
-    const HVARVVAR *var_table;
-    hb_blob_t *var_blob;
+    hb_blob_ptr_t<hmtxvmtx> table;
+    hb_blob_ptr_t<HVARVVAR> var_table;
   };
 
   protected:
-  LongMetric   longMetric[VAR];        /* Paired advance width and leading
+  UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
                                         * bearing values for each glyph. The
                                         * value numOfHMetrics comes from
                                         * the 'hhea' table. If the font is
@@ -304,7 +305,7 @@ struct hmtxvmtx
                                         * be in the array, but that entry is
                                         * required. The last entry applies to
                                         * all subsequent glyphs. */
-/*FWORD                leadingBearingX[VAR];*/ /* Here the advance is assumed
+/*UnsizedArrayOf<FWORD>        leadingBearingX;*//* Here the advance is assumed
                                         * to be the same as the advance
                                         * for the last entry above. The
                                         * number of entries in this array is
@@ -318,20 +319,23 @@ struct hmtxvmtx
                                         * font to vary the side bearing
                                         * values for each glyph. */
   public:
-  DEFINE_SIZE_ARRAY (0, longMetric);
+  DEFINE_SIZE_ARRAY (0, longMetricZ);
 };
 
 struct hmtx : hmtxvmtx<hmtx, hhea> {
-  static const hb_tag_t tableTag       = HB_OT_TAG_hmtx;
-  static const hb_tag_t variationsTag  = HB_OT_TAG_HVAR;
-  static const hb_tag_t os2Tag         = HB_OT_TAG_os2;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
 };
 struct vmtx : hmtxvmtx<vmtx, vhea> {
-  static const hb_tag_t tableTag       = HB_OT_TAG_vmtx;
-  static const hb_tag_t variationsTag  = HB_OT_TAG_VVAR;
-  static const hb_tag_t os2Tag         = HB_TAG_NONE;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
 };
 
+struct hmtx_accelerator_t : hmtx::accelerator_t {};
+struct vmtx_accelerator_t : vmtx::accelerator_t {};
+
 } /* namespace OT */
 
 
index b0fdea4..ec6a3c8 100644 (file)
@@ -27,7 +27,8 @@
 #ifndef HB_OT_KERN_TABLE_HH
 #define HB_OT_KERN_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-aat-layout-kerx-table.hh"
+
 
 /*
  * kern -- Kerning
 namespace OT {
 
 
-struct hb_glyph_pair_t
-{
-  hb_codepoint_t left;
-  hb_codepoint_t right;
-};
-
-struct KernPair
-{
-  inline int get_kerning (void) const
-  { return value; }
-
-  inline int cmp (const hb_glyph_pair_t &o) const
-  {
-    int ret = left.cmp (o.left);
-    if (ret) return ret;
-    return right.cmp (o.right);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  GlyphID      left;
-  GlyphID      right;
-  FWORD                value;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct KernSubTableFormat0
+template <typename KernSubTableHeader>
+struct KernSubTableFormat3
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    hb_glyph_pair_t pair = {left, right};
-    int i = pairs.bsearch (pair);
-    if (i == -1)
+    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
+    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
+    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
+    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
+
+    unsigned int leftC = leftClass[left];
+    unsigned int rightC = rightClass[right];
+    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
       return 0;
-    return pairs[i].get_kerning ();
+    unsigned int i = leftC * rightClassCount + rightC;
+    return kernValue[kernIndex[i]];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool apply (AAT::hb_aat_apply_context_t *c) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (pairs.sanitize (c));
-  }
-
-  protected:
-  BinSearchArrayOf<KernPair> pairs;    /* Array of kerning pairs. */
-  public:
-  DEFINE_SIZE_ARRAY (8, pairs);
-};
+    TRACE_APPLY (this);
 
-struct KernClassTable
-{
-  inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
+    if (!c->plan->requested_kerning)
+      return false;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
-  }
+    if (header.coverage & header.Backwards)
+      return false;
 
-  protected:
-  HBUINT16             firstGlyph;     /* First glyph in class range. */
-  ArrayOf<HBUINT16>    classes;        /* Glyph classes. */
-  public:
-  DEFINE_SIZE_ARRAY (4, classes);
-};
+    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
 
-struct KernSubTableFormat2
-{
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  {
-    unsigned int l = (this+leftClassTable).get_class (left);
-    unsigned int r = (this+rightClassTable).get_class (right);
-    unsigned int offset = l * rowWidth + r * sizeof (FWORD);
-    const FWORD *arr = &(this+array);
-    if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
-      return 0;
-    const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
-    if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
-      return 0;
-    return *v;
+    return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (rowWidth.sanitize (c) &&
-                 leftClassTable.sanitize (c, this) &&
-                 rightClassTable.sanitize (c, this) &&
-                 array.sanitize (c, this));
+    return_trace (c->check_struct (this) &&
+                 c->check_range (kernValueZ,
+                                 kernValueCount * sizeof (FWORD) +
+                                 glyphCount * 2 +
+                                 leftClassCount * rightClassCount));
   }
 
   protected:
-  HBUINT16     rowWidth;       /* The width, in bytes, of a row in the table. */
-  OffsetTo<KernClassTable>
-               leftClassTable; /* Offset from beginning of this subtable to
-                                * left-hand class table. */
-  OffsetTo<KernClassTable>
-               rightClassTable;/* Offset from beginning of this subtable to
-                                * right-hand class table. */
-  OffsetTo<FWORD>
-               array;          /* Offset from beginning of this subtable to
-                                * the start of the kerning array. */
+  KernSubTableHeader   header;
+  HBUINT16             glyphCount;     /* The number of glyphs in this font. */
+  HBUINT8              kernValueCount; /* The number of kerning values. */
+  HBUINT8              leftClassCount; /* The number of left-hand classes. */
+  HBUINT8              rightClassCount;/* The number of right-hand classes. */
+  HBUINT8              flags;          /* Set to zero (reserved for future use). */
+  UnsizedArrayOf<FWORD>        kernValueZ;     /* The kerning values.
+                                        * Length kernValueCount. */
+#if 0
+  UnsizedArrayOf<HBUINT8>leftClass;    /* The left-hand classes.
+                                        * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>rightClass;   /* The right-hand classes.
+                                        * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>kernIndex;    /* The indices into the kernValue array.
+                                        * Length leftClassCount * rightClassCount */
+#endif
   public:
-  DEFINE_SIZE_MIN (8);
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
 };
 
+template <typename KernSubTableHeader>
 struct KernSubTable
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.format; }
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    switch (format) {
+    switch (get_type ()) {
+    /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
     case 0: return u.format0.get_kerning (left, right);
-    case 2: return u.format2.get_kerning (left, right, end);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
   {
-    TRACE_SANITIZE (this);
-    switch (format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:    return_trace (c->dispatch (u.format0));
+    case 1:    return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
+    case 2:    return_trace (c->dispatch (u.format2));
+    case 3:    return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
+    default:   return_trace (c->default_return_value ());
     }
   }
 
-  protected:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.sanitize (c) ||
+                 u.header.length < u.header.min_size ||
+                 !c->check_range (this, u.header.length))) return_trace (false);
+
+    return_trace (dispatch (c));
+  }
+
+  public:
   union {
-  KernSubTableFormat0  format0;
-  KernSubTableFormat2  format2;
+  KernSubTableHeader                           header;
+  AAT::KerxSubTableFormat0<KernSubTableHeader> format0;
+  AAT::KerxSubTableFormat1<KernSubTableHeader> format1;
+  AAT::KerxSubTableFormat2<KernSubTableHeader> format2;
+  KernSubTableFormat3<KernSubTableHeader>      format3;
   } u;
   public:
-  DEFINE_SIZE_MIN (0);
+  DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
 };
 
 
-template <typename T>
-struct KernSubTableWrapper
+struct KernOTSubTableHeader
 {
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline bool is_horizontal (void) const
-  { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
+  static constexpr bool apple = false;
+  typedef AAT::ObsoleteTypes Types;
 
-  inline bool is_override (void) const
-  { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const { return (coverage & Horizontal); }
 
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return is_horizontal () ? get_kerning (left, right, end) : 0; }
-
-  inline unsigned int get_size (void) const { return thiz()->length; }
+  enum Coverage
+  {
+    Horizontal = 0x01u,
+    Minimum    = 0x02u,
+    CrossStream        = 0x04u,
+    Override   = 0x08u,
+
+    /* Not supported: */
+    Backwards  = 0x00u,
+    Variation  = 0x00u,
+  };
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (thiz()) &&
-                 thiz()->length >= T::min_size &&
-                 c->check_array (thiz(), 1, thiz()->length) &&
-                 thiz()->subtable.sanitize (c, thiz()->format));
+    return_trace (c->check_struct (this));
   }
+
+  public:
+  HBUINT16     versionZ;       /* Unused. */
+  HBUINT16     length;         /* Length of the subtable (including this header). */
+  HBUINT8      format;         /* Subtable format. */
+  HBUINT8      coverage;       /* Coverage bits. */
+  public:
+  DEFINE_SIZE_STATIC (6);
 };
 
-template <typename T>
-struct KernTable
+struct KernOT : AAT::KerxTable<KernOT>
 {
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
+  friend struct AAT::KerxTable<KernOT>;
 
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    int v = 0;
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (st->is_override ())
-        v = 0;
-      v += st->get_h_kerning (left, right, table_length + (const char *) this);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-    return v;
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0u;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (thiz()) ||
-                 thiz()->version != T::VERSION))
-      return_trace (false);
-
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!st->sanitize (c)))
-       return_trace (false);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
+  typedef KernOTSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
-    return_trace (true);
-  }
+  protected:
+  HBUINT16     version;        /* Version--0x0000u */
+  HBUINT16     tableCount;     /* Number of subtables in the kerning table. */
+  SubTable     firstSubTable;  /* Subtables. */
+  public:
+  DEFINE_SIZE_MIN (4);
 };
 
-struct KernOT : KernTable<KernOT>
+
+struct KernAATSubTableHeader
 {
-  friend struct KernTable<KernOT>;
+  static constexpr bool apple = true;
+  typedef AAT::ObsoleteTypes Types;
 
-  static const uint16_t VERSION = 0x0000u;
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
 
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
+  enum Coverage
   {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG  = 0x01u,
-      COVERAGE_MINIMUM_FLAG    = 0x02u,
-      COVERAGE_CROSSSTREAM_FLAG        = 0x04u,
-      COVERAGE_OVERRIDE_FLAG   = 0x08u,
-
-      COVERAGE_VARIATION_FLAG  = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS     = 0x07u,
-      COVERAGE_CHECK_HORIZONTAL        = 0x01u
-    };
-
-    protected:
-    HBUINT16   versionZ;       /* Unused. */
-    HBUINT16   length;         /* Length of the subtable (including this header). */
-    HBUINT8    format;         /* Subtable format. */
-    HBUINT8    coverage;       /* Coverage bits. */
-    KernSubTable subtable;     /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (6);
+    Vertical   = 0x80u,
+    CrossStream        = 0x40u,
+    Variation  = 0x20u,
+
+    /* Not supported: */
+    Backwards  = 0x00u,
   };
 
-  protected:
-  HBUINT16     version;        /* Version--0x0000u */
-  HBUINT16     nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8              data[VAR];
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT32     length;         /* Length of the subtable (including this header). */
+  HBUINT8      coverage;       /* Coverage bits. */
+  HBUINT8      format;         /* Subtable format. */
+  HBUINT16     tupleIndex;     /* The tuple index (used for variations fonts).
+                              * This value specifies which tuple this subtable covers.
+                              * Note: We don't implement. */
   public:
-  DEFINE_SIZE_ARRAY (4, data);
+  DEFINE_SIZE_STATIC (8);
 };
 
-struct KernAAT : KernTable<KernAAT>
+struct KernAAT : AAT::KerxTable<KernAAT>
 {
-  friend struct KernTable<KernAAT>;
+  friend struct AAT::KerxTable<KernAAT>;
 
-  static const uint32_t VERSION = 0x00010000u;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0x00010000u;
 
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG  = 0x80u,
-      COVERAGE_CROSSSTREAM_FLAG        = 0x40u,
-      COVERAGE_VARIATION_FLAG  = 0x20u,
-
-      COVERAGE_OVERRIDE_FLAG   = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS     = 0xE0u,
-      COVERAGE_CHECK_HORIZONTAL        = 0x00u
-    };
-
-    protected:
-    HBUINT32   length;         /* Length of the subtable (including this header). */
-    HBUINT8    coverage;       /* Coverage bits. */
-    HBUINT8    format;         /* Subtable format. */
-    HBUINT16   tupleIndex;     /* The tuple index (used for variations fonts).
-                                * This value specifies which tuple this subtable covers. */
-    KernSubTable subtable;     /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (8);
-  };
+  typedef KernAATSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
   protected:
-  HBUINT32             version;        /* Version--0x00010000u */
-  HBUINT32             nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8              data[VAR];
+  HBUINT32     version;        /* Version--0x00010000u */
+  HBUINT32     tableCount;     /* Number of subtables in the kerning table. */
+  SubTable     firstSubTable;  /* Subtables. */
   public:
-  DEFINE_SIZE_ARRAY (8, data);
+  DEFINE_SIZE_MIN (8);
 };
 
 struct kern
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
 
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
+  bool has_data () const { return u.version32; }
+  unsigned int get_type () const { return u.major; }
+
+  bool has_state_machine () const
   {
-    switch (u.major) {
-    case 0: return u.ot.get_h_kerning (left, right, table_length);
-    case 1: return u.aat.get_h_kerning (left, right, table_length);
-    default:return 0;
+    switch (get_type ()) {
+    case 0: return u.ot.has_state_machine ();
+    case 1: return u.aat.has_state_machine ();
+    default:return false;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool has_cross_stream () const
   {
-    TRACE_SANITIZE (this);
-    if (!u.major.sanitize (c)) return_trace (false);
-    switch (u.major) {
-    case 0: return_trace (u.ot.sanitize (c));
-    case 1: return_trace (u.aat.sanitize (c));
-    default:return_trace (true);
+    switch (get_type ()) {
+    case 0: return u.ot.has_cross_stream ();
+    case 1: return u.aat.has_cross_stream ();
+    default:return false;
     }
   }
 
-  struct accelerator_t
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    inline void init (hb_face_t *face)
-    {
-      blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
-      table = blob->as<kern> ();
-      table_length = blob->length;
-    }
-    inline void fini (void)
-    {
-      hb_blob_destroy (blob);
+    switch (get_type ()) {
+    case 0: return u.ot.get_h_kerning (left, right);
+    case 1: return u.aat.get_h_kerning (left, right);
+    default:return 0;
     }
+  }
 
-    inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table->get_h_kerning (left, right, table_length); }
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  { return dispatch (c); }
 
-    private:
-    hb_blob_t *blob;
-    const kern *table;
-    unsigned int table_length;
-  };
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:    return_trace (c->dispatch (u.ot));
+    case 1:    return_trace (c->dispatch (u.aat));
+    default:   return_trace (c->default_return_value ());
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.version32.sanitize (c)) return_trace (false);
+    return_trace (dispatch (c));
+  }
 
   protected:
   union {
+  HBUINT32             version32;
   HBUINT16             major;
   KernOT               ot;
   KernAAT              aat;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, major);
+  DEFINE_SIZE_UNION (4, version32);
 };
 
 } /* namespace OT */
index 33dce89..dd0fba1 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
  * Copyright © 2018  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
 #ifndef HB_OT_LAYOUT_BASE_TABLE_HH
 #define HB_OT_LAYOUT_BASE_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
 
-namespace OT {
+/* To be removed */
+typedef hb_tag_t hb_ot_layout_baseline_t;
 
-#define NOT_INDEXED   ((unsigned int) -1)
+namespace OT {
 
 /*
  * BASE -- Baseline
@@ -42,30 +44,30 @@ namespace OT {
 
 struct BaseCoordFormat1
 {
-  inline int get_coord (void) const { return coordinate; }
+  hb_position_t get_coord () const { return coordinate; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
   HBUINT16     format;         /* Format identifier--format = 1 */
-  HBINT16      coordinate;     /* X or Y value, in design units */
+  FWORD                coordinate;     /* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseCoordFormat2
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord () const
   {
     /* TODO */
     return coordinate;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -73,7 +75,7 @@ struct BaseCoordFormat2
 
   protected:
   HBUINT16     format;         /* Format identifier--format = 2 */
-  HBINT16      coordinate;     /* X or Y value, in design units */
+  FWORD                coordinate;     /* X or Y value, in design units */
   GlyphID      referenceGlyph; /* Glyph ID of control glyph */
   HBUINT16     coordPoint;     /* Index of contour point on the
                                 * reference glyph */
@@ -83,44 +85,53 @@ struct BaseCoordFormat2
 
 struct BaseCoordFormat3
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                          const VariationStore &var_store,
+                          hb_direction_t direction) const
   {
-    /* TODO */
-    return coordinate;
+    const Device &device = this+deviceTable;
+    return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
+                        device.get_y_delta (font, var_store) :
+                        device.get_x_delta (font, var_store));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         deviceTable.sanitize (c, this)));
   }
 
   protected:
-  HBUINT16             format;         /* Format identifier--format = 3 */
-  HBINT16              coordinate;     /* X or Y value, in design units */
-  OffsetTo<Device>     deviceTable;    /* Offset to Device table for X or
-                                        * Y value, from beginning of
-                                        * BaseCoord table (may be NULL). */
+  HBUINT16     format;         /* Format identifier--format = 3 */
+  FWORD                coordinate;     /* X or Y value, in design units */
+  OffsetTo<Device>
+               deviceTable;    /* Offset to Device table for X or
+                                * Y value, from beginning of
+                                * BaseCoord table (may be NULL). */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct BaseCoord
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                          const VariationStore &var_store,
+                          hb_direction_t direction) const
   {
     switch (u.format) {
     case 1: return u.format1.get_coord ();
     case 2: return u.format2.get_coord ();
-    case 3: return u.format3.get_coord ();
+    case 3: return u.format3.get_coord (font, var_store, direction);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
+    if (unlikely (!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));
@@ -142,32 +153,40 @@ struct BaseCoord
 
 struct FeatMinMaxRecord
 {
-  inline int get_min_value (void) const
-  { return (this+minCoord).get_coord(); }
-
-  inline int get_max_value (void) const
-  { return (this+maxCoord).get_coord(); }
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
+    return key < (unsigned int) entry.tag ? -1 :
+          key > (unsigned int) entry.tag ? 1 :
+          0;
+  }
 
-  inline const Tag &get_tag () const
-  { return tag; }
+  void get_min_max (const BaseCoord **min, const BaseCoord **max) const
+  {
+    if (likely (min)) *min = &(this+minCoord);
+    if (likely (max)) *max = &(this+maxCoord);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 minCoord.sanitize (c, base) &&
-                 maxCoord.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                         minCoord.sanitize (c, this) &&
+                         maxCoord.sanitize (c, this)));
   }
 
   protected:
-  Tag                   tag;           /* 4-byte feature identification tag--must
-                                        * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>   minCoord;      /* Offset to BaseCoord table that defines
-                                        * the minimum extent value, from beginning
-                                        * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;      /* Offset to BaseCoord table that defines
-                                        * the maximum extent value, from beginning
-                                        * of MinMax table (may be NULL) */
+  Tag          tag;            /* 4-byte feature identification tag--must
+                                * match feature tag in FeatureList */
+  OffsetTo<BaseCoord>
+               minCoord;       /* Offset to BaseCoord table that defines
+                                * the minimum extent value, from beginning
+                                * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+               maxCoord;       /* Offset to BaseCoord table that defines
+                                * the maximum extent value, from beginning
+                                * of MinMax table (may be NULL) */
   public:
   DEFINE_SIZE_STATIC (8);
 
@@ -175,356 +194,269 @@ struct FeatMinMaxRecord
 
 struct MinMax
 {
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  {
-    /* TODO bsearch */
-    unsigned int count = featMinMaxRecords.len;
-    for (unsigned int i = 0; i < count; i++)
+  void get_min_max (hb_tag_t          feature_tag,
+                          const BaseCoord **min,
+                          const BaseCoord **max) const
+  {
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
+                                         hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
+                                                     featMinMaxRecords.len,
+                                                     FeatMinMaxRecord::static_size,
+                                                     FeatMinMaxRecord::cmp);
+    if (minMaxCoord)
+      minMaxCoord->get_min_max (min, max);
+    else
     {
-      Tag tag = featMinMaxRecords[i].get_tag();
-      int cmp = tag.cmp(featureTableTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
+      if (likely (min)) *min = &(this+minCoord);
+      if (likely (max)) *max = &(this+maxCoord);
     }
-    return NOT_INDEXED;
-  }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+minCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_min_value();
-  }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+maxCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_max_value();
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 minCoord.sanitize (c, this) &&
-                 maxCoord.sanitize (c, this) &&
-                 featMinMaxRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         minCoord.sanitize (c, this) &&
+                         maxCoord.sanitize (c, this) &&
+                         featMinMaxRecords.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseCoord>  minCoord;       /* Offset to BaseCoord table that defines
-                                        * minimum extent value, from the beginning
-                                        * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>  maxCoord;       /* Offset to BaseCoord table that defines
-                                        * maximum extent value, from the beginning
-                                        * of MinMax table (may be NULL) */
-  ArrayOf<FeatMinMaxRecord>
-               featMinMaxRecords;      /* Array of FeatMinMaxRecords, in alphabetical
-                                        * order by featureTableTag */
+  OffsetTo<BaseCoord>
+               minCoord;       /* Offset to BaseCoord table that defines
+                                * minimum extent value, from the beginning
+                                * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+               maxCoord;       /* Offset to BaseCoord table that defines
+                                * maximum extent value, from the beginning
+                                * of MinMax table (may be NULL) */
+  SortedArrayOf<FeatMinMaxRecord>
+               featMinMaxRecords;
+                               /* Array of FeatMinMaxRecords, in alphabetical
+                                * order by featureTableTag */
   public:
   DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
 };
 
-/* TODO... */
-struct BaseLangSysRecord
-{
-  inline const Tag& get_tag(void) const
-  { return baseLangSysTag; }
-
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { return (this+minMax).get_feature_tag_index(featureTableTag); }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_min_value(featureTableTagIndex); }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_max_value(featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 minMax.sanitize (c, base));
-  }
-
-  protected:
-  Tag                  baseLangSysTag;
-  OffsetTo<MinMax>     minMax;
-  public:
-  DEFINE_SIZE_STATIC (6);
-
-};
-
 struct BaseValues
 {
-  inline unsigned int get_default_base_tag_index (void) const
-  { return defaultIndex; }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
   {
-    return (this+baseCoords[baselineTagIndex]).get_coord();
+    if (baseline_tag_index == -1) baseline_tag_index = defaultIndex;
+    return this+baseCoords[baseline_tag_index];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      defaultIndex <= baseCoordCount &&
-      baseCoords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         baseCoords.sanitize (c, this)));
   }
 
   protected:
-  Index                                defaultIndex;
-  HBUINT16                     baseCoordCount;
-  OffsetArrayOf<BaseCoord>     baseCoords;
+  Index                defaultIndex;   /* Index number of default baseline for this
+                                * script — equals index position of baseline tag
+                                * in baselineTags array of the BaseTagList */
+  OffsetArrayOf<BaseCoord>
+               baseCoords;     /* Number of BaseCoord tables defined — should equal
+                                * baseTagCount in the BaseTagList
+                                *
+                                * Array of offsets to BaseCoord tables, from beginning of
+                                * BaseValues table — order matches baselineTags array in
+                                * the BaseTagList */
   public:
-  DEFINE_SIZE_ARRAY (6, baseCoords);
-
+  DEFINE_SIZE_ARRAY (4, baseCoords);
 };
 
-struct BaseScript {
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  {
-    Tag tag;
-    int cmp;
-    for (unsigned int i = 0; i < baseLangSysCount; i++) {
-      tag = baseLangSysRecords[i].get_tag();
-      // taking advantage of alphabetical order
-      cmp = tag.cmp(baseLangSysTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
-    }
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED) {
-      if (unlikely(defaultMinMax)) return NOT_INDEXED;
-      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
-    }
-    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
-    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
-  }
-
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+struct BaseLangSysRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
+    return key < (unsigned int) entry.baseLangSysTag ? -1 :
+          key > (unsigned int) entry.baseLangSysTag ? 1 :
+          0;
   }
 
-  inline unsigned int get_default_base_tag_index (void) const
-  { return (this+baseValues).get_default_base_tag_index(); }
+  const MinMax &get_min_max () const
+  { return this+minMax; }
 
-  inline int get_base_coord (unsigned int baselineTagIndex) const
-  { return (this+baseValues).get_base_coord(baselineTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseValues.sanitize (c, this) &&
-      defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         minMax.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseValues>        baseValues;
-  OffsetTo<MinMax>            defaultMinMax;
-  HBUINT16                      baseLangSysCount;
-  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
-
+  Tag          baseLangSysTag; /* 4-byte language system identification tag */
+  OffsetTo<MinMax>
+               minMax;         /* Offset to MinMax table, from beginning
+                                * of BaseScript table */
   public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+  DEFINE_SIZE_STATIC (6);
 };
 
+struct BaseScript
+{
+  const MinMax &get_min_max (hb_tag_t language_tag) const
+  {
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const BaseLangSysRecord* record = (const BaseLangSysRecord *)
+                                     hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
+                                                 baseLangSysRecords.len,
+                                                 BaseLangSysRecord::static_size,
+                                                 BaseLangSysRecord::cmp);
+    return record ? record->get_min_max () : this+defaultMinMax;
+  }
 
-struct BaseScriptRecord {
-
-  inline const Tag& get_tag (void) const
-  { return baseScriptTag; }
-
-  inline unsigned int get_default_base_tag_index(void) const
-  { return (this+baseScript).get_default_base_tag_index(); }
-
-  inline int get_base_coord(unsigned int baselineTagIndex) const
-  { return (this+baseScript).get_base_coord(baselineTagIndex); }
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
+  { return (this+baseValues).get_base_coord (baseline_tag_index); }
 
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
+  bool is_empty () const { return !baseValues; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScript != Null(OffsetTo<BaseScript>) &&
-      baseScript.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                         baseValues.sanitize (c, this) &&
+                         defaultMinMax.sanitize (c, this) &&
+                         baseLangSysRecords.sanitize (c, this)));
   }
 
   protected:
-  Tag                   baseScriptTag;
-  OffsetTo<BaseScript>  baseScript;
+  OffsetTo<BaseValues>
+               baseValues;     /* Offset to BaseValues table, from beginning
+                                * of BaseScript table (may be NULL) */
+  OffsetTo<MinMax>
+               defaultMinMax;  /* Offset to MinMax table, from beginning of
+                                * BaseScript table (may be NULL) */
+  SortedArrayOf<BaseLangSysRecord>
+               baseLangSysRecords;
+                               /* Number of BaseLangSysRecords
+                                * defined — may be zero (0) */
 
   public:
-    DEFINE_SIZE_STATIC (6);
+  DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
 };
 
-struct BaseScriptList {
-
-  inline unsigned int get_base_script_index (Tag baseScriptTag) const
-  {
-    for (unsigned int i = 0; i < baseScriptCount; i++)
-      if (baseScriptRecords[i].get_tag() == baseScriptTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
-  }
-
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
-  }
-
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
-  }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+struct BaseScriptList;
+struct BaseScriptRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
+    return key < (unsigned int) entry.baseScriptTag ? -1 :
+          key > (unsigned int) entry.baseScriptTag ? 1 :
+          0;
   }
 
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
-  }
+  const BaseScript &get_base_script (const BaseScriptList *list) const
+  { return list+baseScript; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScriptRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         baseScript.sanitize (c, base)));
   }
 
   protected:
-  HBUINT16                    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecords;
+  Tag          baseScriptTag;  /* 4-byte script identification tag */
+  OffsetTo<BaseScript>
+               baseScript;     /* Offset to BaseScript table, from beginning
+                                * of BaseScriptList */
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
+  DEFINE_SIZE_STATIC (6);
 };
 
-struct BaseTagList
+struct BaseScriptList
 {
+  const BaseScriptRecord *find_record (hb_tag_t script) const
+  {
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
+                                                 baseScriptRecords.len,
+                                                 BaseScriptRecord::static_size,
+                                                 BaseScriptRecord::cmp);
+  }
 
-  inline unsigned int get_tag_index(Tag baselineTag) const
+  /* TODO: Or client should handle fallback? */
+  const BaseScript &get_base_script (hb_tag_t script) const
   {
-    for (unsigned int i = 0; i < baseTagCount; i++)
-      if (baselineTags[i] == baselineTag)
-        return i;
-    return NOT_INDEXED;
+    const BaseScriptRecord *record = find_record (script);
+    if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
+
+    return record ? record->get_base_script (this) : Null (BaseScript);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (c->check_struct (this) &&
+                 baseScriptRecords.sanitize (c, this));
   }
 
   protected:
-  HBUINT16        baseTagCount;
-  SortedArrayOf<Tag>  baselineTags;
+  SortedArrayOf<BaseScriptRecord>
+                       baseScriptRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baselineTags);
+  DEFINE_SIZE_ARRAY (2, baseScriptRecords);
 };
 
 struct Axis
 {
-
-  inline unsigned int get_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_ot_layout_baseline_t   baseline,
+                           hb_tag_t                  script_tag,
+                           hb_tag_t                  language_tag,
+                           const BaseCoord         **coord) const
   {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
-    return (this+baseTagList).get_tag_index(baselineTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
-  }
-
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
+    if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
 
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
+    return true;
   }
 
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  bool get_min_max (hb_tag_t          script_tag,
+                   hb_tag_t          language_tag,
+                   hb_tag_t          feature_tag,
+                   const BaseCoord **min_coord,
+                   const BaseCoord **max_coord) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
+    base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
 
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    return true;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                         (this+baseTagList).sanitize (c) &&
+                         (this+baseScriptList).sanitize (c)));
   }
 
   protected:
-  OffsetTo<BaseTagList>     baseTagList;
-  OffsetTo<BaseScriptList>  baseScriptList;
+  OffsetTo<SortedArrayOf<Tag> >
+               baseTagList;    /* Offset to BaseTagList table, from beginning
+                                * of Axis table (may be NULL)
+                                * Array of 4-byte baseline identification tags — must
+                                * be in alphabetical order */
+  OffsetTo<BaseScriptList>
+               baseScriptList; /* Offset to BaseScriptList table, from beginning
+                                * of Axis table
+                                * Array of BaseScriptRecords, in alphabetical order
+                                * by baseScriptTag */
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -532,119 +464,72 @@ struct Axis
 
 struct BASE
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
-
-  inline bool has_vert_axis(void)
-  { return vertAxis != Null(OffsetTo<Axis>); }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline bool has_horiz_axis(void)
-  { return horizAxis != Null(OffsetTo<Axis>); }
+  const Axis &get_axis (hb_direction_t direction) const
+  { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
 
-  // horizontal axis base coords:
+  const VariationStore &get_var_store () const
+  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
 
-  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_font_t               *font,
+                    hb_ot_layout_baseline_t  baseline,
+                    hb_direction_t           direction,
+                    hb_tag_t                 script_tag,
+                    hb_tag_t                 language_tag,
+                    hb_position_t           *base) const
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_base_tag_index(baselineTag);
-  }
+    const BaseCoord *base_coord;
+    if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
+      return false;
 
-  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+    if (likely (base && base_coord)) *base = base_coord->get_coord (font,
+                                                                   get_var_store (),
+                                                                   direction);
+    return true;
   }
 
-  inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  /* TODO: Expose this separately sometime? */
+  bool get_min_max (hb_font_t      *font,
+                   hb_direction_t  direction,
+                   hb_tag_t        script_tag,
+                   hb_tag_t        language_tag,
+                   hb_tag_t        feature_tag,
+                   hb_position_t  *min,
+                   hb_position_t  *max)
   {
-    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // vertical axis base coords:
-
-  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_base_tag_index(baselineTag);
-  }
-
-  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
-
-  inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // horizontal axis min/max coords:
-
-  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
+    const BaseCoord *min_coord, *max_coord;
+    if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,
+                                          &min_coord, &max_coord))
+      return false;
 
-  inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-    // vertical axis min/max coords:
-
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    const VariationStore &var_store = get_var_store ();
+    if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
+    if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
+    return true;
   }
 
-  inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 likely (version.major == 1) &&
-                 horizAxis.sanitize (c, this) &&
-                 vertAxis.sanitize (c, this) &&
-                 (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
+    return_trace (likely (c->check_struct (this) &&
+                         likely (version.major == 1) &&
+                         hAxis.sanitize (c, this) &&
+                         vAxis.sanitize (c, this) &&
+                         (version.to_int () < 0x00010001u || varStore.sanitize (c, this))));
   }
 
   protected:
-  FixedVersion<>  version;
-  OffsetTo<Axis>  horizAxis;
-  OffsetTo<Axis>  vertAxis;
+  FixedVersion<>version;       /* Version of the BASE table */
+  OffsetTo<Axis>hAxis;         /* Offset to horizontal Axis table, from beginning
+                                * of BASE table (may be NULL) */
+  OffsetTo<Axis>vAxis;         /* Offset to vertical Axis table, from beginning
+                                * of BASE table (may be NULL) */
   LOffsetTo<VariationStore>
-               varStore;               /* Offset to the table of Item Variation
-                                        * Store--from beginning of BASE
-                                        * header (may be NULL).  Introduced
-                                        * in version 0x00010001. */
+               varStore;       /* Offset to the table of Item Variation
+                                * Store--from beginning of BASE
+                                * header (may be NULL).  Introduced
+                                * in version 0x00010001. */
   public:
   DEFINE_SIZE_MIN (8);
 };
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
deleted file mode 100644 (file)
index 763ea92..0000000
+++ /dev/null
@@ -1,1773 +0,0 @@
-/*
- * 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
- */
-
-#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
-#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-
-
-#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL   6
-#endif
-#ifndef HB_MAX_CONTEXT_LENGTH
-#define HB_MAX_CONTEXT_LENGTH  64
-#endif
-
-
-namespace OT {
-
-
-#define NOT_COVERED            ((unsigned int) -1)
-
-
-
-/*
- *
- * OpenType Layout Common Table Formats
- *
- */
-
-
-/*
- * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
- */
-
-template <typename Type>
-struct Record
-{
-  inline int cmp (hb_tag_t a) const {
-    return tag.cmp (a);
-  }
-
-  struct sanitize_closure_t {
-    hb_tag_t tag;
-    const void *list_base;
-  };
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    const sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
-  }
-
-  Tag          tag;            /* 4-byte Tag identifier */
-  OffsetTo<Type>
-               offset;         /* Offset from beginning of object holding
-                                * the Record */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type> > {
-  inline const Tag& get_tag (unsigned int i) const
-  {
-    /* We cheat slightly and don't define separate Null objects
-     * for Record types.  Instead, we return the correct Null(Tag)
-     * here. */
-    if (unlikely (i >= this->len)) return Null(Tag);
-    return (*this)[i].tag;
-  }
-  inline unsigned int get_tags (unsigned int start_offset,
-                               unsigned int *record_count /* IN/OUT */,
-                               hb_tag_t     *record_tags /* OUT */) const
-  {
-    if (record_count) {
-      const Record<Type> *arr = this->sub_array (start_offset, record_count);
-      unsigned int count = *record_count;
-      for (unsigned int i = 0; i < count; i++)
-       record_tags[i] = arr[i].tag;
-    }
-    return this->len;
-  }
-  inline bool find_index (hb_tag_t tag, unsigned int *index) const
-  {
-    /* If we want to allow non-sorted data, we can lsearch(). */
-    int i = this->/*lsearch*/bsearch (tag);
-    if (i != -1) {
-        if (index) *index = i;
-        return true;
-    } else {
-      if (index) *index = Index::NOT_FOUND_INDEX;
-      return false;
-    }
-  }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  { return this+RecordArrayOf<Type>::operator [](i).offset; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (RecordArrayOf<Type>::sanitize (c, this));
-  }
-};
-
-
-struct RangeRecord
-{
-  inline int cmp (hb_codepoint_t g) const {
-    return g < start ? -1 : g <= end ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    return glyphs->intersects (start, end);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_range (start, end);
-  }
-
-  GlyphID      start;          /* First GlyphID in the range */
-  GlyphID      end;            /* Last GlyphID in the range */
-  HBUINT16     value;          /* Value */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
-
-
-struct IndexArray : ArrayOf<Index>
-{
-  inline unsigned int get_indexes (unsigned int start_offset,
-                                  unsigned int *_count /* IN/OUT */,
-                                  unsigned int *_indexes /* OUT */) const
-  {
-    if (_count) {
-      const HBUINT16 *arr = this->sub_array (start_offset, _count);
-      unsigned int count = *_count;
-      for (unsigned int i = 0; i < count; i++)
-       _indexes[i] = arr[i];
-    }
-    return this->len;
-  }
-};
-
-
-struct Script;
-struct LangSys;
-struct Feature;
-
-
-struct LangSys
-{
-  inline unsigned int get_feature_count (void) const
-  { return featureIndex.len; }
-  inline hb_tag_t get_feature_index (unsigned int i) const
-  { return featureIndex[i]; }
-  inline unsigned int get_feature_indexes (unsigned int start_offset,
-                                          unsigned int *feature_count /* IN/OUT */,
-                                          unsigned int *feature_indexes /* OUT */) const
-  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
-
-  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
-  inline unsigned int get_required_feature_index (void) const
-  {
-    if (reqFeatureIndex == 0xFFFFu)
-      return Index::NOT_FOUND_INDEX;
-   return reqFeatureIndex;;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       const Record<LangSys>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
-  }
-
-  Offset16     lookupOrderZ;   /* = Null (reserved for an offset to a
-                                * reordering table) */
-  HBUINT16     reqFeatureIndex;/* Index of a feature required for this
-                                * language system--if no required features
-                                * = 0xFFFFu */
-  IndexArray   featureIndex;   /* Array of indices into the FeatureList */
-  public:
-  DEFINE_SIZE_ARRAY (6, featureIndex);
-};
-DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
-
-
-struct Script
-{
-  inline unsigned int get_lang_sys_count (void) const
-  { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
-  { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                        unsigned int *lang_sys_count /* IN/OUT */,
-                                        hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const LangSys& get_lang_sys (unsigned int i) const
-  {
-    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
-    return this+langSys[i].offset;
-  }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
-  { return langSys.find_index (tag, index); }
-
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       const Record<Script>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<LangSys>
-               defaultLangSys; /* Offset to DefaultLangSys table--from
-                                * beginning of Script table--may be Null */
-  RecordArrayOf<LangSys>
-               langSys;        /* Array of LangSysRecords--listed
-                                * alphabetically by LangSysTag */
-  public:
-  DEFINE_SIZE_ARRAY (4, langSys);
-};
-
-typedef RecordListOf<Script> ScriptList;
-
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
-struct FeatureParamsSize
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-
-    /* This subtable has some "history", if you will.  Some earlier versions of
-     * Adobe tools calculated the offset of the FeatureParams sutable from the
-     * beginning of the FeatureList table!  Now, that is dealt with in the
-     * Feature implementation.  But we still need to be able to tell junk from
-     * real data.  Note: We don't check that the nameID actually exists.
-     *
-     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
-     *
-     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
-     * coming out soon, and that the makeotf program will build a font with a
-     * 'size' feature that is correct by the specification.
-     *
-     * The specification for this feature tag is in the "OpenType Layout Tag
-     * Registry". You can see a copy of this at:
-     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
-     *
-     * Here is one set of rules to determine if the 'size' feature is built
-     * correctly, or as by the older versions of MakeOTF. You may be able to do
-     * better.
-     *
-     * Assume that the offset to the size feature is according to specification,
-     * and make the following value checks. If it fails, assume the size
-     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
-     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
-     * offset from the beginning of the FeatureList table, rather than from the
-     * beginning of the 'size' Feature table.
-     *
-     * If "design size" == 0:
-     *     fails check
-     *
-     * Else if ("subfamily identifier" == 0 and
-     *     "range start" == 0 and
-     *     "range end" == 0 and
-     *     "range start" == 0 and
-     *     "menu name ID" == 0)
-     *     passes check: this is the format used when there is a design size
-     * specified, but there is no recommended size range.
-     *
-     * Else if ("design size" <  "range start" or
-     *     "design size" >   "range end" or
-     *     "range end" <= "range start" or
-     *     "menu name ID"  < 256 or
-     *     "menu name ID"  > 32767 or
-     *     menu name ID is not a name ID which is actually in the name table)
-     *     fails test
-     * Else
-     *     passes test.
-     */
-
-    if (!designSize)
-      return_trace (false);
-    else if (subfamilyID == 0 &&
-            subfamilyNameID == 0 &&
-            rangeStart == 0 &&
-            rangeEnd == 0)
-      return_trace (true);
-    else if (designSize < rangeStart ||
-            designSize > rangeEnd ||
-            subfamilyNameID < 256 ||
-            subfamilyNameID > 32767)
-      return_trace (false);
-    else
-      return_trace (true);
-  }
-
-  HBUINT16     designSize;     /* Represents the design size in 720/inch
-                                * units (decipoints).  The design size entry
-                                * must be non-zero.  When there is a design
-                                * size but no recommended size range, the
-                                * rest of the array will consist of zeros. */
-  HBUINT16     subfamilyID;    /* Has no independent meaning, but serves
-                                * as an identifier that associates fonts
-                                * in a subfamily. All fonts which share a
-                                * Preferred or Font Family name and which
-                                * differ only by size range shall have the
-                                * same subfamily value, and no fonts which
-                                * differ in weight or style shall have the
-                                * same subfamily value. If this value is
-                                * zero, the remaining fields in the array
-                                * will be ignored. */
-  HBUINT16     subfamilyNameID;/* If the preceding value is non-zero, this
-                                * value must be set in the range 256 - 32767
-                                * (inclusive). It records the value of a
-                                * field in the name table, which must
-                                * contain English-language strings encoded
-                                * in Windows Unicode and Macintosh Roman,
-                                * and may contain additional strings
-                                * localized to other scripts and languages.
-                                * Each of these strings is the name an
-                                * application should use, in combination
-                                * with the family name, to represent the
-                                * subfamily in a menu.  Applications will
-                                * choose the appropriate version based on
-                                * their selection criteria. */
-  HBUINT16     rangeStart;     /* Large end of the recommended usage range
-                                * (inclusive), stored in 720/inch units
-                                * (decipoints). */
-  HBUINT16     rangeEnd;       /* Small end of the recommended usage range
-                                  (exclusive), stored in 720/inch units
-                                * (decipoints). */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
-struct FeatureParamsStylisticSet
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Right now minorVersion is at zero.  Which means, any table supports
-     * the uiNameID field. */
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16     version;        /* (set to 0): This corresponds to a “minor”
-                                * version number. Additional data may be
-                                * added to the end of this Feature Parameters
-                                * table in the future. */
-
-  NameID       uiNameID;       /* The 'name' table name ID that specifies a
-                                * string (or strings, for multiple languages)
-                                * for a user-interface label for this
-                                * feature.  The values of uiLabelNameId and
-                                * sampleTextNameId are expected to be in the
-                                * font-specific name ID range (256-32767),
-                                * though that is not a requirement in this
-                                * Feature Parameters specification. The
-                                * user-interface label for the feature can
-                                * be provided in multiple languages. An
-                                * English string should be included as a
-                                * fallback. The string should be kept to a
-                                * minimal length to fit comfortably with
-                                * different application interfaces. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
-struct FeatureParamsCharacterVariants
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 characters.sanitize (c));
-  }
-
-  HBUINT16     format;                 /* Format number is set to 0. */
-  NameID       featUILableNameID;      /* The ‘name’ table name ID that
-                                        * specifies a string (or strings,
-                                        * for multiple languages) for a
-                                        * user-interface label for this
-                                        * feature. (May be nullptr.) */
-  NameID       featUITooltipTextNameID;/* The ‘name’ table name ID that
-                                        * specifies a string (or strings,
-                                        * for multiple languages) that an
-                                        * application can use for tooltip
-                                        * text for this feature. (May be
-                                        * nullptr.) */
-  NameID       sampleTextNameID;       /* The ‘name’ table name ID that
-                                        * specifies sample text that
-                                        * illustrates the effect of this
-                                        * feature. (May be nullptr.) */
-  HBUINT16     numNamedParameters;     /* Number of named parameters. (May
-                                        * be zero.) */
-  NameID       firstParamUILabelNameID;/* The first ‘name’ table name ID
-                                        * used to specify strings for
-                                        * user-interface labels for the
-                                        * feature parameters. (Must be zero
-                                        * if numParameters is zero.) */
-  ArrayOf<HBUINT24>
-               characters;             /* Array of the Unicode Scalar Value
-                                        * of the characters for which this
-                                        * feature provides glyph variants.
-                                        * (May be zero.) */
-  public:
-  DEFINE_SIZE_ARRAY (14, characters);
-};
-
-struct FeatureParams
-{
-  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
-  {
-    TRACE_SANITIZE (this);
-    if (tag == HB_TAG ('s','i','z','e'))
-      return_trace (u.size.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-      return_trace (u.stylisticSet.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-      return_trace (u.characterVariants.sanitize (c));
-    return_trace (true);
-  }
-
-  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
-  {
-    if (tag == HB_TAG ('s','i','z','e'))
-      return u.size;
-    return Null(FeatureParamsSize);
-  }
-
-  private:
-  union {
-  FeatureParamsSize                    size;
-  FeatureParamsStylisticSet            stylisticSet;
-  FeatureParamsCharacterVariants       characterVariants;
-  } u;
-  DEFINE_SIZE_STATIC (17);
-};
-
-struct Feature
-{
-  inline unsigned int get_lookup_count (void) const
-  { return lookupIndex.len; }
-  inline hb_tag_t get_lookup_index (unsigned int i) const
-  { return lookupIndex[i]; }
-  inline unsigned int get_lookup_indexes (unsigned int start_index,
-                                         unsigned int *lookup_count /* IN/OUT */,
-                                         unsigned int *lookup_tags /* OUT */) const
-  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
-
-  inline const FeatureParams &get_feature_params (void) const
-  { return this+featureParams; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       const Record<Feature>::sanitize_closure_t *closure = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-      return_trace (false);
-
-    /* Some earlier versions of Adobe tools calculated the offset of the
-     * FeatureParams subtable from the beginning of the FeatureList table!
-     *
-     * If sanitizing "failed" for the FeatureParams subtable, try it with the
-     * alternative location.  We would know sanitize "failed" if old value
-     * of the offset was non-zero, but it's zeroed now.
-     *
-     * Only do this for the 'size' feature, since at the time of the faulty
-     * Adobe tools, only the 'size' feature had FeatureParams defined.
-     */
-
-    OffsetTo<FeatureParams> orig_offset = featureParams;
-    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-      return_trace (false);
-
-    if (likely (orig_offset.is_null ()))
-      return_trace (true);
-
-    if (featureParams == 0 && closure &&
-       closure->tag == HB_TAG ('s','i','z','e') &&
-       closure->list_base && closure->list_base < this)
-    {
-      unsigned int new_offset_int = (unsigned int) orig_offset -
-                                   (((char *) this) - ((char *) closure->list_base));
-
-      OffsetTo<FeatureParams> new_offset;
-      /* Check that it did not overflow. */
-      new_offset.set (new_offset_int);
-      if (new_offset == new_offset_int &&
-         c->try_set (&featureParams, new_offset) &&
-         !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
-       return_trace (false);
-
-      if (c->edit_count > 1)
-        c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
-    }
-
-    return_trace (true);
-  }
-
-  OffsetTo<FeatureParams>
-                featureParams; /* Offset to Feature Parameters table (if one
-                                * has been defined for the feature), relative
-                                * to the beginning of the Feature Table; = Null
-                                * if not required */
-  IndexArray    lookupIndex;   /* Array of LookupList indices */
-  public:
-  DEFINE_SIZE_ARRAY (4, lookupIndex);
-};
-
-typedef RecordListOf<Feature> FeatureList;
-
-
-struct LookupFlag : HBUINT16
-{
-  enum Flags {
-    RightToLeft                = 0x0001u,
-    IgnoreBaseGlyphs   = 0x0002u,
-    IgnoreLigatures    = 0x0004u,
-    IgnoreMarks                = 0x0008u,
-    IgnoreFlags                = 0x000Eu,
-    UseMarkFilteringSet        = 0x0010u,
-    Reserved           = 0x00E0u,
-    MarkAttachmentType = 0xFF00u
-  };
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-} /* namespace OT */
-/* This has to be outside the namespace. */
-HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
-namespace OT {
-
-struct Lookup
-{
-  inline unsigned int get_subtable_count (void) const { return subTable.len; }
-
-  template <typename SubTableType>
-  inline const SubTableType& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
-
-  template <typename SubTableType>
-  inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-  template <typename SubTableType>
-  inline OffsetArrayOf<SubTableType>& get_subtables (void)
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-
-  inline unsigned int get_type (void) const { return lookupType; }
-
-  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
-   * higher 16-bit is mark-filtering-set if the lookup uses one.
-   * Not to be confused with glyph_props which is very similar. */
-  inline uint32_t get_props (void) const
-  {
-    unsigned int flag = lookupFlag;
-    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      flag += (markFilteringSet << 16);
-    }
-    return flag;
-  }
-
-  template <typename SubTableType, typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return_trace (r);
-    }
-    return_trace (c->default_return_value ());
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        unsigned int lookup_type,
-                        uint32_t lookup_props,
-                        unsigned int num_subtables)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    lookupType.set (lookup_type);
-    lookupFlag.set (lookup_props & 0xFFFFu);
-    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      markFilteringSet.set (lookup_props >> 16);
-    }
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
-    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      if (!markFilteringSet.sanitize (c)) return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  private:
-  HBUINT16     lookupType;             /* Different enumerations for GSUB and GPOS */
-  HBUINT16     lookupFlag;             /* Lookup qualifiers */
-  ArrayOf<Offset16>
-               subTable;               /* Array of SubTables */
-  HBUINT16     markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
-                                        * structure. This field is only present if bit
-                                        * UseMarkFilteringSet of lookup flags is set. */
-  public:
-  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
-};
-
-typedef OffsetListOf<Lookup> LookupList;
-
-
-/*
- * Coverage Table
- */
-
-struct CoverageFormat1
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = glyphArray.bsearch (glyph_id);
-    static_assert ((((unsigned int) -1) == NOT_COVERED), "");
-    return i;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      glyphArray[i] = glyphs[i];
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (glyphArray.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    return glyphs->has (glyphArray[index]);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter {
-    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
-    inline bool more (void) { return i < c->glyphArray.len; }
-    inline void next (void) { i++; }
-    inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
-    inline unsigned int get_coverage (void) { return i; }
-
-    private:
-    const struct CoverageFormat1 *c;
-    unsigned int i;
-  };
-  private:
-
-  protected:
-  HBUINT16     coverageFormat; /* Format identifier--format = 1 */
-  SortedArrayOf<GlyphID>
-               glyphArray;     /* Array of GlyphIDs--in numerical order */
-  public:
-  DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (i != -1) {
-      const RangeRecord &range = rangeRecord[i];
-      return (unsigned int) range.value + (glyph_id - range.start);
-    }
-    return NOT_COVERED;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-
-    if (unlikely (!num_glyphs))
-    {
-      rangeRecord.len.set (0);
-      return_trace (true);
-    }
-
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    rangeRecord.len.set (num_ranges);
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
-
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value.set (0);
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i]) {
-       range++;
-       rangeRecord[range].start = glyphs[i];
-       rangeRecord[range].value.set (i);
-        rangeRecord[range].end = glyphs[i];
-      } else {
-        rangeRecord[range].end = glyphs[i];
-      }
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    unsigned int i;
-    unsigned int count = rangeRecord.len;
-    for (i = 0; i < count; i++) {
-      const RangeRecord &range = rangeRecord[i];
-      if (range.value <= index &&
-         index < (unsigned int) range.value + (range.end - range.start) &&
-         range.intersects (glyphs))
-        return true;
-      else if (index < range.value)
-        return false;
-    }
-    return false;
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-        return false;
-    return true;
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter
-  {
-    inline void init (const CoverageFormat2 &c_)
-    {
-      c = &c_;
-      coverage = 0;
-      i = 0;
-      j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
-    }
-    inline bool more (void) { return i < c->rangeRecord.len; }
-    inline void next (void)
-    {
-      if (j >= c->rangeRecord[i].end)
-      {
-        i++;
-       if (more ())
-       {
-         j = c->rangeRecord[i].start;
-         coverage = c->rangeRecord[i].value;
-       }
-       return;
-      }
-      coverage++;
-      j++;
-    }
-    inline hb_codepoint_t get_glyph (void) { return j; }
-    inline unsigned int get_coverage (void) { return coverage; }
-
-    private:
-    const struct CoverageFormat2 *c;
-    unsigned int i, j, coverage;
-  };
-  private:
-
-  protected:
-  HBUINT16     coverageFormat; /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-               rangeRecord;    /* Array of glyph ranges--ordered by
-                                * Start GlyphID. rangeCount entries
-                                * long */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
-  inline 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);
-    default:return NOT_COVERED;
-    }
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
-    default:return_trace (false);
-    }
-  }
-
-  inline 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));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    /* TODO speed this up */
-    Coverage::Iter iter;
-    for (iter.init (*this); iter.more (); iter.next ()) {
-      if (glyphs->has (iter.get_glyph ()))
-        return true;
-    }
-    return false;
-  }
-
-  inline 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);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  struct Iter {
-    Iter (void) : format (0), u () {};
-    inline void init (const Coverage &c_) {
-      format = c_.u.format;
-      switch (format) {
-      case 1: u.format1.init (c_.u.format1); return;
-      case 2: u.format2.init (c_.u.format2); return;
-      default:                               return;
-      }
-    }
-    inline bool more (void) {
-      switch (format) {
-      case 1: return u.format1.more ();
-      case 2: return u.format2.more ();
-      default:return false;
-      }
-    }
-    inline void next (void) {
-      switch (format) {
-      case 1: u.format1.next (); break;
-      case 2: u.format2.next (); break;
-      default:                   break;
-      }
-    }
-    inline hb_codepoint_t get_glyph (void) {
-      switch (format) {
-      case 1: return u.format1.get_glyph ();
-      case 2: return u.format2.get_glyph ();
-      default:return 0;
-      }
-    }
-    inline unsigned int get_coverage (void) {
-      switch (format) {
-      case 1: return u.format1.get_coverage ();
-      case 2: return u.format2.get_coverage ();
-      default:return -1;
-      }
-    }
-
-    private:
-    unsigned int format;
-    union {
-    CoverageFormat2::Iter      format2; /* Put this one first since it's larger; helps shut up compiler. */
-    CoverageFormat1::Iter      format1;
-    } u;
-  };
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  CoverageFormat1      format1;
-  CoverageFormat2      format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Class Definition Table
- */
-
-struct ClassDefFormat1
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    unsigned int i = (unsigned int) (glyph_id - startGlyph);
-    if (unlikely (i < classValue.len))
-      return classValue[i];
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && classValue.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int start = 0;
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i])
-        continue;
-
-      if (start != i)
-       if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
-         return false;
-
-      start = i + 1;
-    }
-    if (start != count)
-      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
-       return false;
-
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i] == klass)
-        glyphs->add (startGlyph + i);
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      if (!hb_set_next (glyphs, &g))
-        return false;
-      if (g < startGlyph)
-        return true;
-      g = startGlyph + count - 1;
-      if (hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (classValue[i] == klass && glyphs->has (startGlyph + i))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16     classFormat;            /* Format identifier--format = 1 */
-  GlyphID      startGlyph;             /* First GlyphID of the classValueArray */
-  ArrayOf<HBUINT16>
-               classValue;             /* Array of Class Values--one per GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (6, classValue);
-};
-
-struct ClassDefFormat2
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (unlikely (i != -1))
-      return rangeRecord[i].value;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value)
-       if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-         return false;
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (rangeRecord[i].value == klass)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-         return false;
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      for (unsigned int i = 0; i < count; i++)
-      {
-       if (!hb_set_next (glyphs, &g))
-         break;
-       if (g < rangeRecord[i].start)
-         return true;
-       g = rangeRecord[i].end;
-      }
-      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16     classFormat;    /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-               rangeRecord;    /* Array of glyph ranges--ordered by
-                                * Start GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct ClassDef
-{
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_class (glyph_id);
-    case 2: return u.format2.get_class (glyph_id);
-    default:return 0;
-    }
-  }
-
-  inline 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));
-    default:return_trace (true);
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.add_class (glyphs, klass);
-    case 2: return u.format2.add_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_class (glyphs, klass);
-    case 2: return u.format2.intersects_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  ClassDefFormat1      format1;
-  ClassDefFormat2      format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Item Variation Store
- */
-
-struct VarRegionAxis
-{
-  inline float evaluate (int coord) const
-  {
-    int start = startCoord, peak = peakCoord, end = endCoord;
-
-    /* TODO Move these to sanitize(). */
-    if (unlikely (start > peak || peak > end))
-      return 1.;
-    if (unlikely (start < 0 && end > 0 && peak != 0))
-      return 1.;
-
-    if (peak == 0 || coord == peak)
-      return 1.;
-
-    if (coord <= start || end <= coord)
-      return 0.;
-
-    /* Interpolate */
-    if (coord < peak)
-      return float (coord - start) / (peak - start);
-    else
-      return float (end - coord) / (end - peak);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
-  }
-
-  public:
-  F2DOT14      startCoord;
-  F2DOT14      peakCoord;
-  F2DOT14      endCoord;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct VarRegionList
-{
-  inline float evaluate (unsigned int region_index,
-                        int *coords, unsigned int coord_len) const
-  {
-    if (unlikely (region_index >= regionCount))
-      return 0.;
-
-    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
-
-    float v = 1.;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      int coord = i < coord_len ? coords[i] : 0;
-      float factor = axes[i].evaluate (coord);
-      if (factor == 0.f)
-        return 0.;
-      v *= factor;
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
-  }
-
-  protected:
-  HBUINT16     axisCount;
-  HBUINT16     regionCount;
-  UnsizedArrayOf<VarRegionAxis>
-               axesZ;
-  public:
-  DEFINE_SIZE_ARRAY (4, axesZ);
-};
-
-struct VarData
-{
-  inline unsigned int get_row_size (void) const
-  { return shortCount + regionIndices.len; }
-
-  inline unsigned int get_size (void) const
-  { return itemCount * get_row_size (); }
-
-  inline float get_delta (unsigned int inner,
-                         int *coords, unsigned int coord_count,
-                         const VarRegionList &regions) const
-  {
-    if (unlikely (inner >= itemCount))
-      return 0.;
-
-   unsigned int count = regionIndices.len;
-   unsigned int scount = shortCount;
-
-   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
-   const HBUINT8 *row = bytes + inner * (scount + count);
-
-   float delta = 0.;
-   unsigned int i = 0;
-
-   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
-   for (; i < scount; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *scursor++;
-   }
-   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
-   for (; i < count; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *bcursor++;
-   }
-
-   return delta;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 regionIndices.sanitize(c) &&
-                 shortCount <= regionIndices.len &&
-                 c->check_array (&StructAfter<HBUINT8> (regionIndices),
-                                 get_row_size (), itemCount));
-  }
-
-  protected:
-  HBUINT16             itemCount;
-  HBUINT16             shortCount;
-  ArrayOf<HBUINT16>    regionIndices;
-  HBUINT8              bytesX[VAR];
-  public:
-  DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
-};
-
-struct VariationStore
-{
-  inline float get_delta (unsigned int outer, unsigned int inner,
-                         int *coords, unsigned int coord_count) const
-  {
-    if (unlikely (outer >= dataSets.len))
-      return 0.;
-
-    return (this+dataSets[outer]).get_delta (inner,
-                                            coords, coord_count,
-                                            this+regions);
-  }
-
-  inline float get_delta (unsigned int index,
-                         int *coords, unsigned int coord_count) const
-  {
-    unsigned int outer = index >> 16;
-    unsigned int inner = index & 0xFFFF;
-    return get_delta (outer, inner, coords, coord_count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 format == 1 &&
-                 regions.sanitize (c, this) &&
-                 dataSets.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16                             format;
-  LOffsetTo<VarRegionList>             regions;
-  OffsetArrayOf<VarData, HBUINT32>     dataSets;
-  public:
-  DEFINE_SIZE_ARRAY (8, dataSets);
-};
-
-/*
- * Feature Variations
- */
-
-struct ConditionFormat1
-{
-  friend struct Condition;
-
-  private:
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
-    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16     format;         /* Format identifier--format = 1 */
-  HBUINT16     axisIndex;
-  F2DOT14      filterRangeMinValue;
-  F2DOT14      filterRangeMaxValue;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct Condition
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
-    default:return false;
-    }
-  }
-
-  inline 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));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  ConditionFormat1     format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct ConditionSet
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    unsigned int count = conditions.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
-        return false;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Condition, HBUINT32> conditions;
-  public:
-  DEFINE_SIZE_ARRAY (2, conditions);
-};
-
-struct FeatureTableSubstitutionRecord
-{
-  friend struct FeatureTableSubstitution;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && feature.sanitize (c, base));
-  }
-
-  protected:
-  HBUINT16             featureIndex;
-  LOffsetTo<Feature>   feature;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct FeatureTableSubstitution
-{
-  inline const Feature *find_substitute (unsigned int feature_index) const
-  {
-    unsigned int count = substitutions.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
-      if (record.featureIndex == feature_index)
-       return &(this+record.feature);
-    }
-    return nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                 likely (version.major == 1) &&
-                 substitutions.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>       version;        /* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
-                       substitutions;
-  public:
-  DEFINE_SIZE_ARRAY (6, substitutions);
-};
-
-struct FeatureVariationRecord
-{
-  friend struct FeatureVariations;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, base) &&
-                 substitutions.sanitize (c, base));
-  }
-
-  protected:
-  LOffsetTo<ConditionSet>
-                       conditions;
-  LOffsetTo<FeatureTableSubstitution>
-                       substitutions;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct FeatureVariations
-{
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
-
-  inline bool find_index (const int *coords, unsigned int coord_len,
-                         unsigned int *index) const
-  {
-    unsigned int count = varRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureVariationRecord &record = varRecords.arrayZ[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
-      {
-       *index = i;
-       return true;
-      }
-    }
-    *index = NOT_FOUND_INDEX;
-    return false;
-  }
-
-  inline const Feature *find_substitute (unsigned int variations_index,
-                                        unsigned int feature_index) const
-  {
-    const FeatureVariationRecord &record = varRecords[variations_index];
-    return (this+record.substitutions).find_substitute (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                 likely (version.major == 1) &&
-                 varRecords.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>       version;        /* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
-                       varRecords;
-  public:
-  DEFINE_SIZE_ARRAY (8, varRecords);
-};
-
-
-/*
- * Device Tables
- */
-
-struct HintingDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font) const
-  { return get_delta (font->x_ppem, font->x_scale); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font) const
-  { return get_delta (font->y_ppem, font->y_scale); }
-
-  inline unsigned int get_size (void) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
-    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
-  }
-
-  private:
-
-  inline int get_delta (unsigned int ppem, int scale) const
-  {
-    if (!ppem) return 0;
-
-    int pixels = get_delta_pixels (ppem);
-
-    if (!pixels) return 0;
-
-    return (int) (pixels * (int64_t) scale / ppem);
-  }
-  inline int get_delta_pixels (unsigned int ppem_size) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3))
-      return 0;
-
-    if (ppem_size < startSize || ppem_size > endSize)
-      return 0;
-
-    unsigned int s = ppem_size - startSize;
-
-    unsigned int byte = deltaValue[s >> (4 - f)];
-    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
-    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
-
-    int delta = bits & mask;
-
-    if ((unsigned int) delta >= ((mask + 1) >> 1))
-      delta -= mask + 1;
-
-    return delta;
-  }
-
-  protected:
-  HBUINT16     startSize;              /* Smallest size to correct--in ppem */
-  HBUINT16     endSize;                /* Largest size to correct--in ppem */
-  HBUINT16     deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
-                                        * 1    Signed 2-bit value, 8 values per uint16
-                                        * 2    Signed 4-bit value, 4 values per uint16
-                                        * 3    Signed 8-bit value, 2 values per uint16
-                                        */
-  HBUINT16     deltaValue[VAR];        /* Array of compressed data */
-  public:
-  DEFINE_SIZE_ARRAY (6, deltaValue);
-};
-
-struct VariationDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_x (get_delta (font, store)); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_y (get_delta (font, store)); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-
-  inline float get_delta (hb_font_t *font, const VariationStore &store) const
-  {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
-  }
-
-  protected:
-  HBUINT16     outerIndex;
-  HBUINT16     innerIndex;
-  HBUINT16     deltaFormat;    /* Format identifier for this table: 0x0x8000 */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct DeviceHeader
-{
-  protected:
-  HBUINT16             reserved1;
-  HBUINT16             reserved2;
-  public:
-  HBUINT16             format;         /* Format identifier */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct Device
-{
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_x_delta (font);
-    case 0x8000:
-      return u.variation.get_x_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_y_delta (font);
-    case 0x8000:
-      return u.variation.get_y_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.b.format.sanitize (c)) return_trace (false);
-    switch (u.b.format) {
-    case 1: case 2: case 3:
-      return_trace (u.hinting.sanitize (c));
-    case 0x8000:
-      return_trace (u.variation.sanitize (c));
-    default:
-      return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  DeviceHeader         b;
-  HintingDevice                hinting;
-  VariationDevice      variation;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (6, b);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
new file mode 100644 (file)
index 0000000..39a8bba
--- /dev/null
@@ -0,0 +1,2178 @@
+/*
+ * 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
+ */
+
+#ifndef HB_OT_LAYOUT_COMMON_HH
+#define HB_OT_LAYOUT_COMMON_HH
+
+#include "hb.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
+
+
+#ifndef HB_MAX_NESTING_LEVEL
+#define HB_MAX_NESTING_LEVEL   6
+#endif
+#ifndef HB_MAX_CONTEXT_LENGTH
+#define HB_MAX_CONTEXT_LENGTH  64
+#endif
+#ifndef HB_CLOSURE_MAX_STAGES
+/*
+ * The maximum number of times a lookup can be applied during shaping.
+ * Used to limit the number of iterations of the closure algorithm.
+ * This must be larger than the number of times add_pause() is
+ * called in a collect_features call of any shaper.
+ */
+#define HB_CLOSURE_MAX_STAGES  32
+#endif
+
+#ifndef HB_MAX_SCRIPTS
+#define HB_MAX_SCRIPTS 500
+#endif
+
+#ifndef HB_MAX_LANGSYS
+#define HB_MAX_LANGSYS 2000
+#endif
+
+
+namespace OT {
+
+
+#define NOT_COVERED            ((unsigned int) -1)
+
+
+
+/*
+ *
+ * OpenType Layout Common Table Formats
+ *
+ */
+
+
+/*
+ * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
+ */
+
+struct Record_sanitize_closure_t {
+  hb_tag_t tag;
+  const void *list_base;
+};
+
+template <typename Type>
+struct Record
+{
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    const Record_sanitize_closure_t closure = {tag, base};
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+  }
+
+  Tag          tag;            /* 4-byte Tag identifier */
+  OffsetTo<Type>
+               offset;         /* Offset from beginning of object holding
+                                * the Record */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename Type>
+struct RecordArrayOf : SortedArrayOf<Record<Type> >
+{
+  const OffsetTo<Type>& get_offset (unsigned int i) const
+  { return (*this)[i].offset; }
+  OffsetTo<Type>& get_offset (unsigned int i)
+  { return (*this)[i].offset; }
+  const Tag& get_tag (unsigned int i) const
+  { return (*this)[i].tag; }
+  unsigned int get_tags (unsigned int start_offset,
+                        unsigned int *record_count /* IN/OUT */,
+                        hb_tag_t     *record_tags /* OUT */) const
+  {
+    if (record_count) {
+      const Record<Type> *arr = this->sub_array (start_offset, record_count);
+      unsigned int count = *record_count;
+      for (unsigned int i = 0; i < count; i++)
+       record_tags[i] = arr[i].tag;
+    }
+    return this->len;
+  }
+  bool find_index (hb_tag_t tag, unsigned int *index) const
+  {
+    return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+};
+
+template <typename Type>
+struct RecordListOf : RecordArrayOf<Type>
+{
+  const Type& operator [] (unsigned int i) const
+  { return this+this->get_offset (i); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct RecordListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->get_offset (i).serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (RecordArrayOf<Type>::sanitize (c, this));
+  }
+};
+
+
+struct RangeRecord
+{
+  int cmp (hb_codepoint_t g) const
+  { return g < start ? -1 : g <= end ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  { return glyphs->intersects (start, end); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  { return glyphs->add_range (start, end); }
+
+  GlyphID      start;          /* First GlyphID in the range */
+  GlyphID      end;            /* Last GlyphID in the range */
+  HBUINT16     value;          /* Value */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
+
+
+struct IndexArray : ArrayOf<Index>
+{
+  unsigned int get_indexes (unsigned int start_offset,
+                           unsigned int *_count /* IN/OUT */,
+                           unsigned int *_indexes /* OUT */) const
+  {
+    if (_count) {
+      const HBUINT16 *arr = this->sub_array (start_offset, _count);
+      unsigned int count = *_count;
+      for (unsigned int i = 0; i < count; i++)
+       _indexes[i] = arr[i];
+    }
+    return this->len;
+  }
+
+  void add_indexes_to (hb_set_t* output /* OUT */) const
+  {
+    output->add_array (arrayZ, len);
+  }
+};
+
+
+struct Script;
+struct LangSys;
+struct Feature;
+
+
+struct LangSys
+{
+  unsigned int get_feature_count () const
+  { return featureIndex.len; }
+  hb_tag_t get_feature_index (unsigned int i) const
+  { return featureIndex[i]; }
+  unsigned int get_feature_indexes (unsigned int start_offset,
+                                   unsigned int *feature_count /* IN/OUT */,
+                                   unsigned int *feature_indexes /* OUT */) const
+  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+  void add_feature_indexes_to (hb_set_t *feature_indexes) const
+  { featureIndex.add_indexes_to (feature_indexes); }
+
+  bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+  unsigned int get_required_feature_index () const
+  {
+    if (reqFeatureIndex == 0xFFFFu)
+      return Index::NOT_FOUND_INDEX;
+   return reqFeatureIndex;;
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+  }
+
+  Offset16     lookupOrderZ;   /* = Null (reserved for an offset to a
+                                * reordering table) */
+  HBUINT16     reqFeatureIndex;/* Index of a feature required for this
+                                * language system--if no required features
+                                * = 0xFFFFu */
+  IndexArray   featureIndex;   /* Array of indices into the FeatureList */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+  unsigned int get_lang_sys_count () const
+  { return langSys.len; }
+  const Tag& get_lang_sys_tag (unsigned int i) const
+  { return langSys.get_tag (i); }
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                 unsigned int *lang_sys_count /* IN/OUT */,
+                                 hb_tag_t     *lang_sys_tags /* OUT */) const
+  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+  const LangSys& get_lang_sys (unsigned int i) const
+  {
+    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+    return this+langSys[i].offset;
+  }
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  { return langSys.find_index (tag, index); }
+
+  bool has_default_lang_sys () const           { return defaultLangSys != 0; }
+  const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Script *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out);
+    unsigned int count = langSys.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+  }
+
+  protected:
+  OffsetTo<LangSys>
+               defaultLangSys; /* Offset to DefaultLangSys table--from
+                                * beginning of Script table--may be Null */
+  RecordArrayOf<LangSys>
+               langSys;        /* Array of LangSysRecords--listed
+                                * alphabetically by LangSysTag */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+typedef RecordListOf<Script> ScriptList;
+
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
+struct FeatureParamsSize
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+
+    /* This subtable has some "history", if you will.  Some earlier versions of
+     * Adobe tools calculated the offset of the FeatureParams sutable from the
+     * beginning of the FeatureList table!  Now, that is dealt with in the
+     * Feature implementation.  But we still need to be able to tell junk from
+     * real data.  Note: We don't check that the nameID actually exists.
+     *
+     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
+     *
+     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
+     * coming out soon, and that the makeotf program will build a font with a
+     * 'size' feature that is correct by the specification.
+     *
+     * The specification for this feature tag is in the "OpenType Layout Tag
+     * Registry". You can see a copy of this at:
+     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
+     *
+     * Here is one set of rules to determine if the 'size' feature is built
+     * correctly, or as by the older versions of MakeOTF. You may be able to do
+     * better.
+     *
+     * Assume that the offset to the size feature is according to specification,
+     * and make the following value checks. If it fails, assume the size
+     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
+     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
+     * offset from the beginning of the FeatureList table, rather than from the
+     * beginning of the 'size' Feature table.
+     *
+     * If "design size" == 0:
+     *     fails check
+     *
+     * Else if ("subfamily identifier" == 0 and
+     *     "range start" == 0 and
+     *     "range end" == 0 and
+     *     "range start" == 0 and
+     *     "menu name ID" == 0)
+     *     passes check: this is the format used when there is a design size
+     * specified, but there is no recommended size range.
+     *
+     * Else if ("design size" <  "range start" or
+     *     "design size" >   "range end" or
+     *     "range end" <= "range start" or
+     *     "menu name ID"  < 256 or
+     *     "menu name ID"  > 32767 or
+     *     menu name ID is not a name ID which is actually in the name table)
+     *     fails test
+     * Else
+     *     passes test.
+     */
+
+    if (!designSize)
+      return_trace (false);
+    else if (subfamilyID == 0 &&
+            subfamilyNameID == 0 &&
+            rangeStart == 0 &&
+            rangeEnd == 0)
+      return_trace (true);
+    else if (designSize < rangeStart ||
+            designSize > rangeEnd ||
+            subfamilyNameID < 256 ||
+            subfamilyNameID > 32767)
+      return_trace (false);
+    else
+      return_trace (true);
+  }
+
+  HBUINT16     designSize;     /* Represents the design size in 720/inch
+                                * units (decipoints).  The design size entry
+                                * must be non-zero.  When there is a design
+                                * size but no recommended size range, the
+                                * rest of the array will consist of zeros. */
+  HBUINT16     subfamilyID;    /* Has no independent meaning, but serves
+                                * as an identifier that associates fonts
+                                * in a subfamily. All fonts which share a
+                                * Preferred or Font Family name and which
+                                * differ only by size range shall have the
+                                * same subfamily value, and no fonts which
+                                * differ in weight or style shall have the
+                                * same subfamily value. If this value is
+                                * zero, the remaining fields in the array
+                                * will be ignored. */
+  NameID       subfamilyNameID;/* If the preceding value is non-zero, this
+                                * value must be set in the range 256 - 32767
+                                * (inclusive). It records the value of a
+                                * field in the name table, which must
+                                * contain English-language strings encoded
+                                * in Windows Unicode and Macintosh Roman,
+                                * and may contain additional strings
+                                * localized to other scripts and languages.
+                                * Each of these strings is the name an
+                                * application should use, in combination
+                                * with the family name, to represent the
+                                * subfamily in a menu.  Applications will
+                                * choose the appropriate version based on
+                                * their selection criteria. */
+  HBUINT16     rangeStart;     /* Large end of the recommended usage range
+                                * (inclusive), stored in 720/inch units
+                                * (decipoints). */
+  HBUINT16     rangeEnd;       /* Small end of the recommended usage range
+                                  (exclusive), stored in 720/inch units
+                                * (decipoints). */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
+struct FeatureParamsStylisticSet
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* Right now minorVersion is at zero.  Which means, any table supports
+     * the uiNameID field. */
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16     version;        /* (set to 0): This corresponds to a “minor”
+                                * version number. Additional data may be
+                                * added to the end of this Feature Parameters
+                                * table in the future. */
+
+  NameID       uiNameID;       /* The 'name' table name ID that specifies a
+                                * string (or strings, for multiple languages)
+                                * for a user-interface label for this
+                                * feature.  The values of uiLabelNameId and
+                                * sampleTextNameId are expected to be in the
+                                * font-specific name ID range (256-32767),
+                                * though that is not a requirement in this
+                                * Feature Parameters specification. The
+                                * user-interface label for the feature can
+                                * be provided in multiple languages. An
+                                * English string should be included as a
+                                * fallback. The string should be kept to a
+                                * minimal length to fit comfortably with
+                                * different application interfaces. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
+struct FeatureParamsCharacterVariants
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 characters.sanitize (c));
+  }
+
+  HBUINT16     format;                 /* Format number is set to 0. */
+  NameID       featUILableNameID;      /* The ‘name’ table name ID that
+                                        * specifies a string (or strings,
+                                        * for multiple languages) for a
+                                        * user-interface label for this
+                                        * feature. (May be NULL.) */
+  NameID       featUITooltipTextNameID;/* The ‘name’ table name ID that
+                                        * specifies a string (or strings,
+                                        * for multiple languages) that an
+                                        * application can use for tooltip
+                                        * text for this feature. (May be
+                                        * nullptr.) */
+  NameID       sampleTextNameID;       /* The ‘name’ table name ID that
+                                        * specifies sample text that
+                                        * illustrates the effect of this
+                                        * feature. (May be NULL.) */
+  HBUINT16     numNamedParameters;     /* Number of named parameters. (May
+                                        * be zero.) */
+  NameID       firstParamUILabelNameID;/* The first ‘name’ table name ID
+                                        * used to specify strings for
+                                        * user-interface labels for the
+                                        * feature parameters. (Must be zero
+                                        * if numParameters is zero.) */
+  ArrayOf<HBUINT24>
+               characters;             /* Array of the Unicode Scalar Value
+                                        * of the characters for which this
+                                        * feature provides glyph variants.
+                                        * (May be zero.) */
+  public:
+  DEFINE_SIZE_ARRAY (14, characters);
+};
+
+struct FeatureParams
+{
+  bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
+  {
+    TRACE_SANITIZE (this);
+    if (tag == HB_TAG ('s','i','z','e'))
+      return_trace (u.size.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return_trace (u.stylisticSet.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return_trace (u.characterVariants.sanitize (c));
+    return_trace (true);
+  }
+
+  const FeatureParamsSize& get_size_params (hb_tag_t tag) const
+  {
+    if (tag == HB_TAG ('s','i','z','e'))
+      return u.size;
+    return Null (FeatureParamsSize);
+  }
+
+  const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return u.stylisticSet;
+    return Null (FeatureParamsStylisticSet);
+  }
+
+  const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return u.characterVariants;
+    return Null (FeatureParamsCharacterVariants);
+  }
+
+  private:
+  union {
+  FeatureParamsSize                    size;
+  FeatureParamsStylisticSet            stylisticSet;
+  FeatureParamsCharacterVariants       characterVariants;
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (17);
+};
+
+struct Feature
+{
+  unsigned int get_lookup_count () const
+  { return lookupIndex.len; }
+  hb_tag_t get_lookup_index (unsigned int i) const
+  { return lookupIndex[i]; }
+  unsigned int get_lookup_indexes (unsigned int start_index,
+                                  unsigned int *lookup_count /* IN/OUT */,
+                                  unsigned int *lookup_tags /* OUT */) const
+  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
+  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
+  { lookupIndex.add_indexes_to (lookup_indexes); }
+
+  const FeatureParams &get_feature_params () const
+  { return this+featureParams; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Feature *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->featureParams.set (0); /* TODO(subset) FeatureParams. */
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                const Record_sanitize_closure_t *closure = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
+      return_trace (false);
+
+    /* Some earlier versions of Adobe tools calculated the offset of the
+     * FeatureParams subtable from the beginning of the FeatureList table!
+     *
+     * If sanitizing "failed" for the FeatureParams subtable, try it with the
+     * alternative location.  We would know sanitize "failed" if old value
+     * of the offset was non-zero, but it's zeroed now.
+     *
+     * Only do this for the 'size' feature, since at the time of the faulty
+     * Adobe tools, only the 'size' feature had FeatureParams defined.
+     */
+
+    OffsetTo<FeatureParams> orig_offset = featureParams;
+    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
+      return_trace (false);
+
+    if (likely (orig_offset.is_null ()))
+      return_trace (true);
+
+    if (featureParams == 0 && closure &&
+       closure->tag == HB_TAG ('s','i','z','e') &&
+       closure->list_base && closure->list_base < this)
+    {
+      unsigned int new_offset_int = (unsigned int) orig_offset -
+                                   (((char *) this) - ((char *) closure->list_base));
+
+      OffsetTo<FeatureParams> new_offset;
+      /* Check that it did not overflow. */
+      new_offset.set (new_offset_int);
+      if (new_offset == new_offset_int &&
+         c->try_set (&featureParams, new_offset) &&
+         !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
+       return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  OffsetTo<FeatureParams>
+                featureParams; /* Offset to Feature Parameters table (if one
+                                * has been defined for the feature), relative
+                                * to the beginning of the Feature Table; = Null
+                                * if not required */
+  IndexArray    lookupIndex;   /* Array of LookupList indices */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
+};
+
+typedef RecordListOf<Feature> FeatureList;
+
+
+struct LookupFlag : HBUINT16
+{
+  enum Flags {
+    RightToLeft                = 0x0001u,
+    IgnoreBaseGlyphs   = 0x0002u,
+    IgnoreLigatures    = 0x0004u,
+    IgnoreMarks                = 0x0008u,
+    IgnoreFlags                = 0x000Eu,
+    UseMarkFilteringSet        = 0x0010u,
+    Reserved           = 0x00E0u,
+    MarkAttachmentType = 0xFF00u
+  };
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+} /* namespace OT */
+/* This has to be outside the namespace. */
+HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
+namespace OT {
+
+struct Lookup
+{
+  unsigned int get_subtable_count () const { return subTable.len; }
+
+  template <typename TSubTable>
+  const TSubTable& get_subtable (unsigned int i) const
+  { return this+CastR<OffsetArrayOf<TSubTable> > (subTable)[i]; }
+
+  template <typename TSubTable>
+  const OffsetArrayOf<TSubTable>& get_subtables () const
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+  template <typename TSubTable>
+  OffsetArrayOf<TSubTable>& get_subtables ()
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+
+  unsigned int get_size () const
+  {
+    const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+      return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
+    return (const char *) &markFilteringSet - (const char *) this;
+  }
+
+  unsigned int get_type () const { return lookupType; }
+
+  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
+   * higher 16-bit is mark-filtering-set if the lookup uses one.
+   * Not to be confused with glyph_props which is very similar. */
+  uint32_t get_props () const
+  {
+    unsigned int flag = lookupFlag;
+    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      flag += (markFilteringSet << 16);
+    }
+    return flag;
+  }
+
+  template <typename TSubTable, typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int lookup_type = get_type ();
+    TRACE_DISPATCH (this, lookup_type);
+    unsigned int count = get_subtable_count ();
+    for (unsigned int i = 0; i < count; i++) {
+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type);
+      if (c->stop_sublookup_iteration (r))
+       return_trace (r);
+    }
+    return_trace (c->default_return_value ());
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 unsigned int lookup_type,
+                 uint32_t lookup_props,
+                 unsigned int num_subtables)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lookupType.set (lookup_type);
+    lookupFlag.set (lookup_props & 0xFFFFu);
+    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      if (unlikely (!c->extend (*this))) return_trace (false);
+      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      markFilteringSet.set (lookup_props >> 16);
+    }
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSubsetWrapper
+  {
+    SubTableSubsetWrapper (const TSubTable &subtable_,
+                          unsigned int lookup_type_) :
+                            subtable (subtable_),
+                            lookup_type (lookup_type_) {}
+
+    bool subset (hb_subset_context_t *c) const
+    { return subtable.dispatch (c, lookup_type); }
+
+    private:
+    const TSubTable &subtable;
+    unsigned int lookup_type;
+  };
+
+  template <typename TSubTable>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Lookup *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    /* Subset the actual subtables. */
+    /* TODO Drop empty ones, either by calling intersects() beforehand,
+     * or just dropping null offsets after. */
+    const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
+    OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
+    unsigned int count = subTable.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      SubTableSubsetWrapper<TSubTable> wrapper (this+subtables[i], get_type ());
+
+      out_subtables[i].serialize_subset (c, wrapper, out);
+    }
+
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSanitizeWrapper : TSubTable
+  {
+    bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
+    { return this->dispatch (c, lookup_type); }
+  };
+
+  template <typename TSubTable>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      if (!markFilteringSet.sanitize (c)) return_trace (false);
+    }
+
+    if (unlikely (!CastR<OffsetArrayOf<SubTableSanitizeWrapper<TSubTable> > > (subTable)
+                  .sanitize (c, this, get_type ())))
+      return_trace (false);
+
+    if (unlikely (get_type () == TSubTable::Extension))
+    {
+      /* The spec says all subtables of an Extension lookup should
+       * have the same type, which shall not be the Extension type
+       * itself (but we already checked for that).
+       * This is specially important if one has a reverse type! */
+      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
+      unsigned int count = get_subtable_count ();
+      for (unsigned int i = 1; i < count; i++)
+       if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
+         return_trace (false);
+    }
+    return_trace (true);
+    return_trace (true);
+  }
+
+  private:
+  HBUINT16     lookupType;             /* Different enumerations for GSUB and GPOS */
+  HBUINT16     lookupFlag;             /* Lookup qualifiers */
+  ArrayOf<Offset16>
+               subTable;               /* Array of SubTables */
+/*HBUINT16     markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
+                                        * structure. This field is only present if bit
+                                        * UseMarkFilteringSet of lookup flags is set. */
+  public:
+  DEFINE_SIZE_ARRAY (6, subTable);
+};
+
+typedef OffsetListOf<Lookup> LookupList;
+
+
+/*
+ * Coverage Table
+ */
+
+struct CoverageFormat1
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    unsigned int i;
+    glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
+    return i;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (glyphArray.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (glyphArray.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = glyphArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphs->has (glyphArray[i]))
+       return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  { return glyphs->has (glyphArray[index]); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter {
+    void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
+    void fini () {}
+    bool more () { return i < c->glyphArray.len; }
+    void next () { i++; }
+    hb_codepoint_t get_glyph () { return c->glyphArray[i]; }
+    unsigned int get_coverage () { return i; }
+
+    private:
+    const struct CoverageFormat1 *c;
+    unsigned int i;
+  };
+  private:
+
+  protected:
+  HBUINT16     coverageFormat; /* Format identifier--format = 1 */
+  SortedArrayOf<GlyphID>
+               glyphArray;     /* Array of GlyphIDs--in numerical order */
+  public:
+  DEFINE_SIZE_ARRAY (4, glyphArray);
+};
+
+struct CoverageFormat2
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    const RangeRecord &range = rangeRecord.bsearch (glyph_id);
+    return likely (range.start <= range.end) ?
+          (unsigned int) range.value + (glyph_id - range.start) :
+          NOT_COVERED;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+       num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (0);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i])
+      {
+       range++;
+       rangeRecord[range].start = glyphs[i];
+       rangeRecord[range].value.set (i);
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+       return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    unsigned int i;
+    unsigned int count = rangeRecord.len;
+    for (i = 0; i < count; i++) {
+      const RangeRecord &range = rangeRecord[i];
+      if (range.value <= index &&
+         index < (unsigned int) range.value + (range.end - range.start) &&
+         range.intersects (glyphs))
+       return true;
+      else if (index < range.value)
+       return false;
+    }
+    return false;
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+       return false;
+    return true;
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter
+  {
+    void init (const CoverageFormat2 &c_)
+    {
+      c = &c_;
+      coverage = 0;
+      i = 0;
+      j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
+      if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
+      {
+       /* Broken table. Skip. */
+       i = c->rangeRecord.len;
+      }
+    }
+    void fini () {}
+    bool more () { return i < c->rangeRecord.len; }
+    void next ()
+    {
+      if (j >= c->rangeRecord[i].end)
+      {
+       i++;
+       if (more ())
+       {
+         hb_codepoint_t old = j;
+         j = c->rangeRecord[i].start;
+         if (unlikely (j <= old))
+         {
+           /* Broken table. Skip. Important to avoid DoS. */
+          i = c->rangeRecord.len;
+          return;
+         }
+         coverage = c->rangeRecord[i].value;
+       }
+       return;
+      }
+      coverage++;
+      j++;
+    }
+    hb_codepoint_t get_glyph () { return j; }
+    unsigned int get_coverage () { return coverage; }
+
+    private:
+    const struct CoverageFormat2 *c;
+    unsigned int i, coverage;
+    hb_codepoint_t j;
+  };
+  private:
+
+  protected:
+  HBUINT16     coverageFormat; /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+               rangeRecord;    /* Array of glyph ranges--ordered by
+                                * Start GlyphID. rangeCount entries
+                                * long */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct Coverage
+{
+  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);
+    default:return NOT_COVERED;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+       num_ranges++;
+    u.format.set (glyphs.length * 2 < num_ranges * 3 ? 1 : 2);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
+    default:return_trace (false);
+    }
+  }
+
+  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));
+    default:return_trace (true);
+    }
+  }
+
+  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);
+    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);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  struct Iter
+  {
+    Iter (const Coverage &c_)
+    {
+      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;
+      default:                              return;
+      }
+    }
+    bool more ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.more ();
+      case 2: return u.format2.more ();
+      default:return false;
+      }
+    }
+    void next ()
+    {
+      switch (format)
+      {
+      case 1: u.format1.next (); break;
+      case 2: u.format2.next (); break;
+      default:                  break;
+      }
+    }
+    hb_codepoint_t get_glyph ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_glyph ();
+      case 2: return u.format2.get_glyph ();
+      default:return 0;
+      }
+    }
+    unsigned int get_coverage ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_coverage ();
+      case 2: return u.format2.get_coverage ();
+      default:return -1;
+      }
+    }
+
+    private:
+    unsigned int format;
+    union {
+    CoverageFormat2::Iter      format2; /* Put this one first since it's larger; helps shut up compiler. */
+    CoverageFormat1::Iter      format1;
+    } u;
+  };
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  CoverageFormat1      format1;
+  CoverageFormat2      format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+
+/*
+ * Class Definition Table
+ */
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                      hb_array_t<const GlyphID> glyphs,
+                                      hb_array_t<const HBUINT16> klasses);
+
+struct ClassDefFormat1
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return classValue[(unsigned int) (glyph_id - startGlyph)];
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const HBUINT16> glyphs,
+                 hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      startGlyph.set (0);
+      classValue.len.set (0);
+      return_trace (true);
+    }
+
+    hb_codepoint_t glyph_min = glyphs[0];
+    hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+    startGlyph.set (glyph_min);
+    classValue.len.set (glyph_max - glyph_min + 1);
+    if (unlikely (!c->extend (classValue))) return_trace (false);
+
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      classValue[glyphs[i] - glyph_min] = klasses[i];
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end   = start + classValue.len;
+    for (hb_codepoint_t g = start; g < end; g++)
+    {
+      unsigned int value = classValue[g - start];
+      if (!value) continue;
+      if (!glyphset.has (g)) continue;
+      glyphs.push()->set (glyph_map[g]);
+      klasses.push()->set (value);
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classValue.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int start = 0;
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (classValue[i])
+       continue;
+
+      if (start != i)
+       if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
+         return false;
+
+      start = i + 1;
+    }
+    if (start != count)
+      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
+       return false;
+
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass) glyphs->add (startGlyph + i);
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next()? */
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end = startGlyph + classValue.len;
+    for (hb_codepoint_t iter = startGlyph - 1;
+        hb_set_next (glyphs, &iter) && iter < end;)
+      if (classValue[iter - start]) return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      if (!hb_set_next (glyphs, &g)) return false;
+      if (g < startGlyph) return true;
+      g = startGlyph + count - 1;
+      if (hb_set_next (glyphs, &g)) return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass && glyphs->has (startGlyph + i))
+       return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16     classFormat;    /* Format identifier--format = 1 */
+  GlyphID      startGlyph;     /* First GlyphID of the classValueArray */
+  ArrayOf<HBUINT16>
+               classValue;     /* Array of Class Values--one per GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (6, classValue);
+};
+
+struct ClassDefFormat2
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return rangeRecord.bsearch (glyph_id).value;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const HBUINT16> glyphs,
+                 hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+         klasses[i - 1] != klasses[i])
+       num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (klasses[0]);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+         klasses[i - 1] != klasses[i])
+      {
+       range++;
+       rangeRecord[range].start = glyphs[i];
+       rangeRecord[range].value = klasses[i];
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      unsigned int value = rangeRecord[i].value;
+      if (!value) continue;
+      hb_codepoint_t start = rangeRecord[i].start;
+      hb_codepoint_t end   = rangeRecord[i].end + 1;
+      for (hb_codepoint_t g = start; g < end; g++)
+      {
+       if (!glyphset.has (g)) continue;
+       glyphs.push ()->set (glyph_map[g]);
+       klasses.push ()->set (value);
+      }
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value)
+       if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+         return false;
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (rangeRecord[i].value == klass)
+       if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+         return false;
+    }
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+       return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      for (unsigned int i = 0; i < count; i++)
+      {
+       if (!hb_set_next (glyphs, &g))
+         break;
+       if (g < rangeRecord[i].start)
+         return true;
+       g = rangeRecord[i].end;
+      }
+      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+       return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
+       return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16     classFormat;    /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+               rangeRecord;    /* Array of glyph ranges--ordered by
+                                * Start GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct ClassDef
+{
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_class (glyph_id);
+    case 2: return u.format2.get_class (glyph_id);
+    default:return 0;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int format = 2;
+    if (glyphs.length)
+    {
+      hb_codepoint_t glyph_min = glyphs[0];
+      hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+      unsigned int num_ranges = 1;
+      for (unsigned int i = 1; i < glyphs.length; i++)
+       if (glyphs[i - 1] + 1 != glyphs[i] ||
+           klasses[i - 1] != klasses[i])
+         num_ranges++;
+
+      if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
+        format = 1;
+    }
+    u.format.set (format);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
+    case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
+    default:return_trace (false);
+    }
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    switch (u.format) {
+    case 1: return_trace (u.format1.subset (c));
+    case 2: return_trace (u.format2.subset (c));
+    default:return_trace (false);
+    }
+  }
+
+  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));
+    default:return_trace (true);
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_class (glyphs, klass);
+    case 2: return u.format2.add_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  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);
+    default:return false;
+    }
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersects_class (glyphs, klass);
+    case 2: return u.format2.intersects_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  ClassDefFormat1      format1;
+  ClassDefFormat2      format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                      hb_array_t<const GlyphID> glyphs,
+                                      hb_array_t<const HBUINT16> klasses)
+{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
+
+
+/*
+ * Item Variation Store
+ */
+
+struct VarRegionAxis
+{
+  float evaluate (int coord) const
+  {
+    int start = startCoord, peak = peakCoord, end = endCoord;
+
+    /* TODO Move these to sanitize(). */
+    if (unlikely (start > peak || peak > end))
+      return 1.;
+    if (unlikely (start < 0 && end > 0 && peak != 0))
+      return 1.;
+
+    if (peak == 0 || coord == peak)
+      return 1.;
+
+    if (coord <= start || end <= coord)
+      return 0.;
+
+    /* Interpolate */
+    if (coord < peak)
+      return float (coord - start) / (peak - start);
+    else
+      return float (end - coord) / (end - peak);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+    /* TODO Handle invalid start/peak/end configs, so we don't
+     * have to do that at runtime. */
+  }
+
+  public:
+  F2DOT14      startCoord;
+  F2DOT14      peakCoord;
+  F2DOT14      endCoord;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct VarRegionList
+{
+  float evaluate (unsigned int region_index,
+                        const int *coords, unsigned int coord_len) const
+  {
+    if (unlikely (region_index >= regionCount))
+      return 0.;
+
+    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
+
+    float v = 1.;
+    unsigned int count = axisCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      int coord = i < coord_len ? coords[i] : 0;
+      float factor = axes[i].evaluate (coord);
+      if (factor == 0.f)
+       return 0.;
+      v *= factor;
+    }
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
+  }
+
+  unsigned int get_region_count () const { return regionCount; }
+
+  protected:
+  HBUINT16     axisCount;
+  HBUINT16     regionCount;
+  UnsizedArrayOf<VarRegionAxis>
+               axesZ;
+  public:
+  DEFINE_SIZE_ARRAY (4, axesZ);
+};
+
+struct VarData
+{
+  unsigned int get_region_index_count () const
+  { return regionIndices.len; }
+
+  unsigned int get_row_size () const
+  { return shortCount + regionIndices.len; }
+
+  unsigned int get_size () const
+  { return itemCount * get_row_size (); }
+
+  float get_delta (unsigned int inner,
+                         const int *coords, unsigned int coord_count,
+                         const VarRegionList &regions) const
+  {
+    if (unlikely (inner >= itemCount))
+      return 0.;
+
+   unsigned int count = regionIndices.len;
+   unsigned int scount = shortCount;
+
+   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
+   const HBUINT8 *row = bytes + inner * (scount + count);
+
+   float delta = 0.;
+   unsigned int i = 0;
+
+   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+   for (; i < scount; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *scursor++;
+   }
+   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
+   for (; i < count; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *bcursor++;
+   }
+
+   return delta;
+  }
+
+  void get_scalars (int *coords, unsigned int coord_count,
+                    const VarRegionList &regions,
+                    float *scalars /*OUT */,
+                    unsigned int num_scalars) const
+  {
+    assert (num_scalars == regionIndices.len);
+   for (unsigned int i = 0; i < num_scalars; i++)
+   {
+     scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+   }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 regionIndices.sanitize (c) &&
+                 shortCount <= regionIndices.len &&
+                 c->check_range (&StructAfter<HBUINT8> (regionIndices),
+                                 itemCount,
+                                 get_row_size ()));
+  }
+
+  protected:
+  HBUINT16             itemCount;
+  HBUINT16             shortCount;
+  ArrayOf<HBUINT16>    regionIndices;
+/*UnsizedArrayOf<HBUINT8>bytesX;*/
+  public:
+  DEFINE_SIZE_ARRAY (6, regionIndices);
+};
+
+struct VariationStore
+{
+  float get_delta (unsigned int outer, unsigned int inner,
+                  const int *coords, unsigned int coord_count) const
+  {
+    if (unlikely (outer >= dataSets.len))
+      return 0.;
+
+    return (this+dataSets[outer]).get_delta (inner,
+                                            coords, coord_count,
+                                            this+regions);
+  }
+
+  float get_delta (unsigned int index,
+                  const int *coords, unsigned int coord_count) const
+  {
+    unsigned int outer = index >> 16;
+    unsigned int inner = index & 0xFFFF;
+    return get_delta (outer, inner, coords, coord_count);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 format == 1 &&
+                 regions.sanitize (c, this) &&
+                 dataSets.sanitize (c, this));
+  }
+
+  unsigned int get_region_index_count (unsigned int ivs) const
+  { return (this+dataSets[ivs]).get_region_index_count (); }
+
+  void get_scalars (unsigned int ivs,
+                   int *coords, unsigned int coord_count,
+                   float *scalars /*OUT*/,
+                   unsigned int num_scalars) const
+  {
+    (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
+                                      &scalars[0], num_scalars);
+  }
+
+  protected:
+  HBUINT16                             format;
+  LOffsetTo<VarRegionList>             regions;
+  LOffsetArrayOf<VarData>              dataSets;
+  public:
+  DEFINE_SIZE_ARRAY (8, dataSets);
+};
+
+/*
+ * Feature Variations
+ */
+
+struct ConditionFormat1
+{
+  friend struct Condition;
+
+  private:
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
+    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier--format = 1 */
+  HBUINT16     axisIndex;
+  F2DOT14      filterRangeMinValue;
+  F2DOT14      filterRangeMaxValue;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct Condition
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.evaluate (coords, coord_len);
+    default:return false;
+    }
+  }
+
+  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));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  ConditionFormat1     format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct ConditionSet
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
+       return false;
+    return true;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  LOffsetArrayOf<Condition>    conditions;
+  public:
+  DEFINE_SIZE_ARRAY (2, conditions);
+};
+
+struct FeatureTableSubstitutionRecord
+{
+  friend struct FeatureTableSubstitution;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && feature.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16             featureIndex;
+  LOffsetTo<Feature>   feature;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct FeatureTableSubstitution
+{
+  const Feature *find_substitute (unsigned int feature_index) const
+  {
+    unsigned int count = substitutions.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
+      if (record.featureIndex == feature_index)
+       return &(this+record.feature);
+    }
+    return nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                 likely (version.major == 1) &&
+                 substitutions.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>       version;        /* Version--0x00010000u */
+  ArrayOf<FeatureTableSubstitutionRecord>
+                       substitutions;
+  public:
+  DEFINE_SIZE_ARRAY (6, substitutions);
+};
+
+struct FeatureVariationRecord
+{
+  friend struct FeatureVariations;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, base) &&
+                 substitutions.sanitize (c, base));
+  }
+
+  protected:
+  LOffsetTo<ConditionSet>
+                       conditions;
+  LOffsetTo<FeatureTableSubstitution>
+                       substitutions;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct FeatureVariations
+{
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
+
+  bool find_index (const int *coords, unsigned int coord_len,
+                         unsigned int *index) const
+  {
+    unsigned int count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureVariationRecord &record = varRecords.arrayZ[i];
+      if ((this+record.conditions).evaluate (coords, coord_len))
+      {
+       *index = i;
+       return true;
+      }
+    }
+    *index = NOT_FOUND_INDEX;
+    return false;
+  }
+
+  const Feature *find_substitute (unsigned int variations_index,
+                                 unsigned int feature_index) const
+  {
+    const FeatureVariationRecord &record = varRecords[variations_index];
+    return (this+record.substitutions).find_substitute (feature_index);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                 likely (version.major == 1) &&
+                 varRecords.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>       version;        /* Version--0x00010000u */
+  LArrayOf<FeatureVariationRecord>
+                       varRecords;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
+};
+
+
+/*
+ * Device Tables
+ */
+
+struct HintingDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font) const
+  { return get_delta (font->x_ppem, font->x_scale); }
+
+  hb_position_t get_y_delta (hb_font_t *font) const
+  { return get_delta (font->y_ppem, font->y_scale); }
+
+  unsigned int get_size () const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
+    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
+  }
+
+  private:
+
+  int get_delta (unsigned int ppem, int scale) const
+  {
+    if (!ppem) return 0;
+
+    int pixels = get_delta_pixels (ppem);
+
+    if (!pixels) return 0;
+
+    return (int) (pixels * (int64_t) scale / ppem);
+  }
+  int get_delta_pixels (unsigned int ppem_size) const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3))
+      return 0;
+
+    if (ppem_size < startSize || ppem_size > endSize)
+      return 0;
+
+    unsigned int s = ppem_size - startSize;
+
+    unsigned int byte = deltaValueZ[s >> (4 - f)];
+    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
+    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
+
+    int delta = bits & mask;
+
+    if ((unsigned int) delta >= ((mask + 1) >> 1))
+      delta -= mask + 1;
+
+    return delta;
+  }
+
+  protected:
+  HBUINT16     startSize;              /* Smallest size to correct--in ppem */
+  HBUINT16     endSize;                /* Largest size to correct--in ppem */
+  HBUINT16     deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
+                                        * 1    Signed 2-bit value, 8 values per uint16
+                                        * 2    Signed 4-bit value, 4 values per uint16
+                                        * 3    Signed 8-bit value, 2 values per uint16
+                                        */
+  UnsizedArrayOf<HBUINT16>
+               deltaValueZ;            /* Array of compressed data */
+  public:
+  DEFINE_SIZE_ARRAY (6, deltaValueZ);
+};
+
+struct VariationDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_x (get_delta (font, store)); }
+
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_y (get_delta (font, store)); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  private:
+
+  float get_delta (hb_font_t *font, const VariationStore &store) const
+  {
+    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
+  }
+
+  protected:
+  HBUINT16     outerIndex;
+  HBUINT16     innerIndex;
+  HBUINT16     deltaFormat;    /* Format identifier for this table: 0x0x8000 */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DeviceHeader
+{
+  protected:
+  HBUINT16             reserved1;
+  HBUINT16             reserved2;
+  public:
+  HBUINT16             format;         /* Format identifier */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct Device
+{
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_x_delta (font);
+    case 0x8000:
+      return u.variation.get_x_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_y_delta (font);
+    case 0x8000:
+      return u.variation.get_y_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.b.format.sanitize (c)) return_trace (false);
+    switch (u.b.format) {
+    case 1: case 2: case 3:
+      return_trace (u.hinting.sanitize (c));
+    case 0x8000:
+      return_trace (u.variation.sanitize (c));
+    default:
+      return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  DeviceHeader         b;
+  HintingDevice                hinting;
+  VariationDevice      variation;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (6, b);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_COMMON_HH */
index 60a8d3a..06c26fb 100644 (file)
@@ -29,9 +29,9 @@
 #ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
 #define HB_OT_LAYOUT_GDEF_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
 
 
 namespace OT {
@@ -46,10 +46,10 @@ typedef ArrayOf<HBUINT16> AttachPoint;      /* Array of contour point indices--in
 
 struct AttachList
 {
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                        unsigned int start_offset,
-                                        unsigned int *point_count /* IN/OUT */,
-                                        unsigned int *point_array /* OUT */) const
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                 unsigned int start_offset,
+                                 unsigned int *point_count /* IN/OUT */,
+                                 unsigned int *point_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -61,9 +61,10 @@ struct AttachList
 
     const AttachPoint &points = this+attachPoint[index];
 
-    if (point_count) {
-      const HBUINT16 *array = points.sub_array (start_offset, point_count);
-      unsigned int count = *point_count;
+    if (point_count)
+    {
+      hb_array_t<const HBUINT16> array = points.sub_array (start_offset, point_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
        point_array[i] = array[i];
     }
@@ -71,7 +72,7 @@ struct AttachList
     return points.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
@@ -97,12 +98,12 @@ struct CaretValueFormat1
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -120,16 +121,14 @@ struct CaretValueFormat2
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     hb_position_t x, y;
-    if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
-      return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-    else
-      return 0;
+    font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
+    return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -146,14 +145,15 @@ struct CaretValueFormat3
 {
   friend struct CaretValue;
 
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
+                                const VariationStore &var_store) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
@@ -172,7 +172,7 @@ struct CaretValueFormat3
 
 struct CaretValue
 {
-  inline hb_position_t get_caret_value (hb_font_t *font,
+  hb_position_t get_caret_value (hb_font_t *font,
                                        hb_direction_t direction,
                                        hb_codepoint_t glyph_id,
                                        const VariationStore &var_store) const
@@ -185,7 +185,7 @@ struct CaretValue
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -210,17 +210,18 @@ struct CaretValue
 
 struct LigGlyph
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                     hb_direction_t direction,
-                                     hb_codepoint_t glyph_id,
-                                     const VariationStore &var_store,
-                                     unsigned int start_offset,
-                                     unsigned int *caret_count /* IN/OUT */,
-                                     hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                              hb_direction_t direction,
+                              hb_codepoint_t glyph_id,
+                              const VariationStore &var_store,
+                              unsigned int start_offset,
+                              unsigned int *caret_count /* IN/OUT */,
+                              hb_position_t *caret_array /* OUT */) const
   {
-    if (caret_count) {
-      const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
-      unsigned int count = *caret_count;
+    if (caret_count)
+    {
+      hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
        caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
     }
@@ -228,7 +229,7 @@ struct LigGlyph
     return carets.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (carets.sanitize (c, this));
@@ -245,13 +246,13 @@ struct LigGlyph
 
 struct LigCaretList
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                     hb_direction_t direction,
-                                     hb_codepoint_t glyph_id,
-                                     const VariationStore &var_store,
-                                     unsigned int start_offset,
-                                     unsigned int *caret_count /* IN/OUT */,
-                                     hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                              hb_direction_t direction,
+                              hb_codepoint_t glyph_id,
+                              const VariationStore &var_store,
+                              unsigned int start_offset,
+                              unsigned int *caret_count /* IN/OUT */,
+                              hb_position_t *caret_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -264,7 +265,7 @@ struct LigCaretList
     return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
@@ -284,10 +285,10 @@ struct LigCaretList
 
 struct MarkGlyphSetsFormat1
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this));
@@ -304,7 +305,7 @@ struct MarkGlyphSetsFormat1
 
 struct MarkGlyphSets
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
     case 1: return u.format1.covers (set_index, glyph_id);
@@ -312,7 +313,7 @@ struct MarkGlyphSets
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -337,9 +338,10 @@ struct MarkGlyphSets
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
  */
 
+
 struct GDEF
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_GDEF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
 
   enum GlyphClasses {
     UnclassifiedGlyph  = 0,
@@ -349,59 +351,47 @@ struct GDEF
     ComponentGlyph     = 4
   };
 
-  inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
-  inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
+  bool has_data () const { return version.to_int (); }
+  bool has_glyph_classes () const { return glyphClassDef != 0; }
+  unsigned int get_glyph_class (hb_codepoint_t glyph) const
   { return (this+glyphClassDef).get_class (glyph); }
-  inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
+  void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
   { (this+glyphClassDef).add_class (glyphs, klass); }
 
-  inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
-  inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
+  bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
+  unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
   { return (this+markAttachClassDef).get_class (glyph); }
 
-  inline bool has_attach_points (void) const { return attachList != 0; }
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                        unsigned int start_offset,
-                                        unsigned int *point_count /* IN/OUT */,
-                                        unsigned int *point_array /* OUT */) const
+  bool has_attach_points () const { return attachList != 0; }
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                 unsigned int start_offset,
+                                 unsigned int *point_count /* IN/OUT */,
+                                 unsigned int *point_array /* OUT */) const
   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
 
-  inline bool has_lig_carets (void) const { return ligCaretList != 0; }
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                     hb_direction_t direction,
-                                     hb_codepoint_t glyph_id,
-                                     unsigned int start_offset,
-                                     unsigned int *caret_count /* IN/OUT */,
-                                     hb_position_t *caret_array /* OUT */) const
+  bool has_lig_carets () const { return ligCaretList != 0; }
+  unsigned int get_lig_carets (hb_font_t *font,
+                              hb_direction_t direction,
+                              hb_codepoint_t glyph_id,
+                              unsigned int start_offset,
+                              unsigned int *caret_count /* IN/OUT */,
+                              hb_position_t *caret_array /* OUT */) const
   { return (this+ligCaretList).get_lig_carets (font,
                                               direction, glyph_id, get_var_store(),
                                               start_offset, caret_count, caret_array); }
 
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
-  inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
+  bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
 
-  inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
-  inline const VariationStore &get_var_store (void) const
+  bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
+  const VariationStore &get_var_store () const
   { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                 likely (version.major == 1) &&
-                 glyphClassDef.sanitize (c, this) &&
-                 attachList.sanitize (c, this) &&
-                 ligCaretList.sanitize (c, this) &&
-                 markAttachClassDef.sanitize (c, this) &&
-                 (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-                 (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
-  }
-
   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
-   * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
+   * glyph class and other bits, and high 8-bit the mark attachment type (if any).
    * Not to be confused with lookup_props which is very similar. */
-  inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
+  unsigned int get_glyph_props (hb_codepoint_t glyph) const
   {
     unsigned int klass = get_glyph_class (glyph);
 
@@ -419,6 +409,65 @@ struct GDEF
     }
   }
 
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                  hb_face_t *face) const;
+
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+       hb_blob_destroy (this->table.get_blob ());
+       this->table = hb_blob_get_empty ();
+      }
+    }
+
+    void fini () { this->table.destroy (); }
+
+    hb_blob_ptr_t<GDEF> table;
+  };
+
+  unsigned int get_size () const
+  {
+    return min_size +
+          (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+          (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GDEF *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out);
+    out->attachList.set (0);//TODO(subset) serialize_subset (c, this+attachList, out);
+    out->ligCaretList.set (0);//TODO(subset) serialize_subset (c, this+ligCaretList, out);
+    out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out);
+
+    if (version.to_int () >= 0x00010002u)
+      out->markGlyphSetsDef.set (0);// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out);
+
+    if (version.to_int () >= 0x00010003u)
+      out->varStore.set (0);// TODO(subset) serialize_subset (c, this+varStore, out);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                 likely (version.major == 1) &&
+                 glyphClassDef.sanitize (c, this) &&
+                 attachList.sanitize (c, this) &&
+                 ligCaretList.sanitize (c, this) &&
+                 markAttachClassDef.sanitize (c, this) &&
+                 (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+                 (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+  }
 
   protected:
   FixedVersion<>version;               /* Version of the GDEF table--currently
@@ -453,6 +502,7 @@ struct GDEF
   DEFINE_SIZE_MIN (12);
 };
 
+struct GDEF_accelerator_t : GDEF::accelerator_t {};
 
 } /* namespace OT */
 
index bc8a5fd..e17a282 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
 #define HB_OT_LAYOUT_GPOS_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
@@ -53,7 +53,7 @@ enum attach_type_t {
 
 typedef HBUINT16 Value;
 
-typedef Value ValueRecord[VAR];
+typedef UnsizedArrayOf<Value> ValueRecord;
 
 struct ValueFormat : HBUINT16
 {
@@ -84,79 +84,79 @@ struct ValueFormat : HBUINT16
   HBINT16              yAdvance;               /* Vertical adjustment for advance--in
                                         * design units (only used for vertical
                                         * writing) */
-  Offset       xPlaDevice;             /* Offset to Device table for
+  OffsetTo<Device>     xPlaDevice;     /* Offset to Device table for
                                         * horizontal placement--measured from
                                         * beginning of PosTable (may be NULL) */
-  Offset       yPlaDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>     yPlaDevice;     /* Offset to Device table for vertical
                                         * placement--measured from beginning
                                         * of PosTable (may be NULL) */
-  Offset       xAdvDevice;             /* Offset to Device table for
+  OffsetTo<Device>     xAdvDevice;     /* Offset to Device table for
                                         * horizontal advance--measured from
                                         * beginning of PosTable (may be NULL) */
-  Offset       yAdvDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>     yAdvDevice;     /* Offset to Device table for vertical
                                         * advance--measured from beginning of
                                         * PosTable (may be NULL) */
 #endif
 
-  inline unsigned int get_len (void) const
-  { return _hb_popcount ((unsigned int) *this); }
-  inline unsigned int get_size (void) const
-  { return get_len () * Value::static_size; }
+  unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
+  unsigned int get_size () const { return get_len () * Value::static_size; }
 
-  void apply_value (hb_ot_apply_context_t   *c,
+  bool apply_value (hb_ot_apply_context_t   *c,
                    const void           *base,
                    const Value          *values,
                    hb_glyph_position_t  &glyph_pos) const
   {
+    bool ret = false;
     unsigned int format = *this;
-    if (!format) return;
+    if (!format) return ret;
 
     hb_font_t *font = c->font;
-    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
 
-    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
+    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++, &ret));
+    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++, &ret));
     if (format & xAdvance) {
-      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
+      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
       values++;
     }
     /* y_advance values grow downward but font-space grows upward, hence negation */
     if (format & yAdvance) {
-      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
+      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
       values++;
     }
 
-    if (!has_device ()) return;
+    if (!has_device ()) return ret;
 
     bool use_x_device = font->x_ppem || font->num_coords;
     bool use_y_device = font->y_ppem || font->num_coords;
 
-    if (!use_x_device && !use_y_device) return;
+    if (!use_x_device && !use_y_device) return ret;
 
     const VariationStore &store = c->var_store;
 
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
+      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
+      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
     if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
+      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yAdvDevice) {
       /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
+      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
+    return ret;
   }
 
   private:
-  inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     unsigned int format = *this;
 
@@ -173,39 +173,46 @@ struct ValueFormat : HBUINT16
     return true;
   }
 
-  static inline OffsetTo<Device>& get_device (Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
-  static inline const OffsetTo<Device>& get_device (const Value* value)
+  static OffsetTo<Device>& get_device (Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
+  static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<OffsetTo<Device> > (value);
+  }
 
-  static inline const HBINT16& get_short (const Value* value)
-  { return *CastP<HBINT16> (value); }
+  static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<HBINT16> (value);
+  }
 
   public:
 
-  inline bool has_device (void) const {
+  bool has_device () const
+  {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
-  inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
   }
 
-  inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+  bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
     unsigned int len = get_len ();
 
-    if (!c->check_array (values, get_size (), count)) return_trace (false);
+    if (!c->check_range (values, count, get_size ())) return_trace (false);
 
     if (!has_device ()) return_trace (true);
 
     for (unsigned int i = 0; i < count; i++) {
       if (!sanitize_value_devices (c, base, values))
-        return_trace (false);
+       return_trace (false);
       values += len;
     }
 
@@ -213,7 +220,7 @@ struct ValueFormat : HBUINT16
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
   {
     TRACE_SANITIZE (this);
 
@@ -221,7 +228,7 @@ struct ValueFormat : HBUINT16
 
     for (unsigned int i = 0; i < count; i++) {
       if (!sanitize_value_devices (c, base, values))
-        return_trace (false);
+       return_trace (false);
       values += stride;
     }
 
@@ -232,15 +239,15 @@ struct ValueFormat : HBUINT16
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                         float *x, float *y) const
+  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);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -256,22 +263,22 @@ struct AnchorFormat1
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                         float *x, float *y) const
+  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;
     unsigned int x_ppem = font->x_ppem;
     unsigned int y_ppem = font->y_ppem;
     hb_position_t cx = 0, cy = 0;
-    hb_bool_t ret;
+    bool ret;
 
     ret = (x_ppem || y_ppem) &&
-          font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+         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);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -288,8 +295,8 @@ struct AnchorFormat2
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                         float *x, float *y) const
+  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);
@@ -301,7 +308,7 @@ struct AnchorFormat3
       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  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));
@@ -325,8 +332,8 @@ struct AnchorFormat3
 
 struct Anchor
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                         float *x, float *y) const
+  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) {
@@ -337,7 +344,7 @@ struct Anchor
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -363,20 +370,22 @@ struct Anchor
 
 struct AnchorMatrix
 {
-  inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
+  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];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+  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_int_mul_overflows (rows, cols))) return_trace (false);
+    if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
-    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
+    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);
@@ -384,8 +393,8 @@ struct AnchorMatrix
 
   HBUINT16     rows;                   /* Number of rows */
   protected:
-  OffsetTo<Anchor>
-               matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
+  UnsizedArrayOf<OffsetTo<Anchor> >
+               matrixZ;                /* Matrix of offsets to Anchor tables--
                                         * from beginning of AnchorMatrix table */
   public:
   DEFINE_SIZE_ARRAY (2, matrixZ);
@@ -396,7 +405,7 @@ struct MarkRecord
 {
   friend struct MarkArray;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
@@ -413,10 +422,10 @@ struct MarkRecord
 
 struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */
 {
-  inline bool apply (hb_ot_apply_context_t *c,
-                    unsigned int mark_index, unsigned int glyph_index,
-                    const AnchorMatrix &anchors, unsigned int class_count,
-                    unsigned int glyph_pos) const
+  bool apply (hb_ot_apply_context_t *c,
+             unsigned int mark_index, unsigned int glyph_index,
+             const AnchorMatrix &anchors, unsigned int class_count,
+             unsigned int glyph_pos) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -447,7 +456,7 @@ struct MarkArray : ArrayOf<MarkRecord>      /* Array of MarkRecords--in Coverage orde
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
@@ -459,18 +468,15 @@ struct MarkArray : ArrayOf<MarkRecord>    /* Array of MarkRecords--in Coverage orde
 
 struct SinglePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -483,7 +489,14 @@ struct SinglePosFormat1
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -507,18 +520,15 @@ struct SinglePosFormat1
 
 struct SinglePosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -535,7 +545,14 @@ struct SinglePosFormat2
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -560,7 +577,7 @@ struct SinglePosFormat2
 struct SinglePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,19 +615,36 @@ struct PairSet
 {
   friend struct PairPosFormat1;
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c,
+  bool intersects (const hb_set_t *glyphs,
+                         const ValueFormat *valueFormats) const
+  {
+    unsigned int len1 = valueFormats[0].get_len ();
+    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+    const PairValueRecord *record = &firstPairValueRecord;
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (glyphs->has (record->secondGlyph))
+       return true;
+      record = &StructAtOffset<const PairValueRecord> (record, record_size);
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
                              const ValueFormat *valueFormats) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
     c->input->add_array (&record->secondGlyph, len, record_size);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c,
+  bool apply (hb_ot_apply_context_t *c,
                     const ValueFormat *valueFormats,
                     unsigned int pos) const
   {
@@ -620,7 +654,6 @@ struct PairSet
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
 
     /* Hand-coded bsearch. */
@@ -630,18 +663,19 @@ struct PairSet
     int min = 0, max = (int) count - 1;
     while (min <= max)
     {
-      int mid = (min + max) / 2;
-      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
       hb_codepoint_t mid_x = record->secondGlyph;
       if (x < mid_x)
-        max = mid - 1;
+       max = mid - 1;
       else if (x > mid_x)
-        min = mid + 1;
+       min = mid + 1;
       else
       {
-        buffer->unsafe_to_break (buffer->idx, pos + 1);
-       valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
-       valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+       /* Note the intentional use of "|" instead of short-circuit "||". */
+       if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
+           valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+         buffer->unsafe_to_break (buffer->idx, pos + 1);
        if (len2)
          pos++;
        buffer->idx = pos;
@@ -652,50 +686,65 @@ struct PairSet
     return_trace (false);
   }
 
-  struct sanitize_closure_t {
+  struct sanitize_closure_t
+  {
     const void *base;
     const ValueFormat *valueFormats;
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+  bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
+       && c->check_range (&firstPairValueRecord,
+                         len,
+                         HBUINT16::static_size,
+                         closure->stride))) return_trace (false);
 
     unsigned int count = len;
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
                  closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
-  HBUINT16     len;                    /* Number of PairValueRecords */
-  HBUINT16     arrayZ[VAR];            /* Array of PairValueRecords--ordered
-                                        * by GlyphID of the second glyph */
+  HBUINT16             len;    /* Number of PairValueRecords */
+  PairValueRecord      firstPairValueRecord;
+                               /* Array of PairValueRecords--ordered
+                                * by GlyphID of the second glyph */
   public:
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  DEFINE_SIZE_MIN (2);
 };
 
 struct PairPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    unsigned int count = pairSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+         (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
+       return true;
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = pairSet.len;
     for (unsigned int i = 0; i < count; i++)
       (this+pairSet[i]).collect_glyphs (c, valueFormat);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -709,7 +758,14 @@ struct PairPosFormat1
     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
@@ -717,7 +773,8 @@ struct PairPosFormat1
 
     unsigned int len1 = valueFormat[0].get_len ();
     unsigned int len2 = valueFormat[1].get_len ();
-    PairSet::sanitize_closure_t closure = {
+    PairSet::sanitize_closure_t closure =
+    {
       this,
       valueFormat,
       len1,
@@ -747,19 +804,21 @@ struct PairPosFormat1
 
 struct PairPosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
+    return (this+coverage).intersects (glyphs) &&
+          (this+classDef2).intersects (glyphs);
   }
 
-  inline const Coverage &get_coverage (void) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    return this+coverage;
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+    if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -778,10 +837,11 @@ struct PairPosFormat2
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
-    buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c, this, v, buffer->cur_pos());
-    valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+    /* Note the intentional use of "|" instead of short-circuit "||". */
+    if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
+       valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+      buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
 
     buffer->idx = skippy_iter.idx;
     if (len2)
@@ -790,7 +850,14 @@ struct PairPosFormat2
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
@@ -803,7 +870,9 @@ struct PairPosFormat2
     unsigned int stride = len1 + len2;
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
-    return_trace (c->check_array (values, record_size, count) &&
+    return_trace (c->check_range ((const void *) values,
+                                 count,
+                                 record_size) &&
                  valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
                  valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
@@ -841,7 +910,7 @@ struct PairPosFormat2
 struct PairPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -865,7 +934,7 @@ struct EntryExitRecord
 {
   friend struct CursivePosFormat1;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
@@ -889,39 +958,36 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
 
 struct CursivePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
+
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
-    if (!this_record.exitAnchor) return_trace (false);
+    if (!this_record.entryAnchor) return_trace (false);
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
+    if (!skippy_iter.prev ()) return_trace (false);
 
-    const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
-    if (!next_record.entryAnchor) return_trace (false);
+    const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
+    if (!prev_record.exitAnchor) return_trace (false);
 
-    unsigned int i = buffer->idx;
-    unsigned int j = skippy_iter.idx;
+    unsigned int i = skippy_iter.idx;
+    unsigned int j = buffer->idx;
 
     buffer->unsafe_to_break (i, j);
     float entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+    (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+    (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
 
     hb_glyph_position_t *pos = buffer->pos;
 
@@ -968,7 +1034,7 @@ struct CursivePosFormat1
      * parent.
      *
      * Optimize things for the case of RightToLeft, as that's most common in
-     * Arabinc. */
+     * Arabic. */
     unsigned int child  = i;
     unsigned int parent = j;
     hb_position_t x_offset = entry_x - exit_x;
@@ -997,11 +1063,18 @@ struct CursivePosFormat1
     else
       pos[child].x_offset = x_offset;
 
-    buffer->idx = j;
+    buffer->idx++;
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
@@ -1022,7 +1095,7 @@ struct CursivePosFormat1
 struct CursivePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1047,19 +1120,19 @@ typedef AnchorMatrix BaseArray;         /* base-major--
 
 struct MarkBasePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+          (this+baseCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1074,10 +1147,13 @@ struct MarkBasePosFormat1
       if (!skippy_iter.prev ()) return_trace (false);
       /* We only want to attach to the first of a MultipleSubst sequence.
        * https://github.com/harfbuzz/harfbuzz/issues/740
-       * Reject others. */
+       * Reject others...
+       * ...but stop if we find a mark in the MultipleSubst sequence:
+       * https://github.com/harfbuzz/harfbuzz/issues/1020 */
       if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
          0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
          (skippy_iter.idx == 0 ||
+          _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
           _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
           _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
           _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
@@ -1085,7 +1161,7 @@ struct MarkBasePosFormat1
           ))
        break;
       skippy_iter.reject ();
-    } while (1);
+    } while (true);
 
     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
@@ -1096,7 +1172,14 @@ struct MarkBasePosFormat1
     return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1128,7 +1211,7 @@ struct MarkBasePosFormat1
 struct MarkBasePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1158,19 +1241,19 @@ typedef OffsetListOf<LigatureAttach> LigatureArray;
 
 struct MarkLigPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+          (this+ligatureCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1213,7 +1296,14 @@ struct MarkLigPosFormat1
     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1246,7 +1336,7 @@ struct MarkLigPosFormat1
 struct MarkLigPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1271,19 +1361,19 @@ typedef AnchorMatrix Mark2Array;        /* mark2-major--
 
 struct MarkMarkPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+mark1Coverage).intersects (glyphs) &&
+          (this+mark2Coverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
     if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+mark1Coverage;
-  }
+  const Coverage &get_coverage () const { return this+mark1Coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1309,7 +1399,7 @@ struct MarkMarkPosFormat1
       if (id1 == 0) /* Marks belonging to the same base. */
        goto good;
       else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
-        goto good;
+       goto good;
     } else {
       /* If ligature ids don't match, it may be the case that one of the marks
        * itself is a ligature.  In which case match. */
@@ -1327,7 +1417,14 @@ struct MarkMarkPosFormat1
     return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1361,7 +1458,7 @@ struct MarkMarkPosFormat1
 struct MarkMarkPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1385,7 +1482,7 @@ struct ChainContextPos : ChainContext {};
 
 struct ExtensionPos : Extension<ExtensionPos>
 {
-  typedef struct PosLookupSubTable LookupSubTable;
+  typedef struct PosLookupSubTable SubTable;
 };
 
 
@@ -1397,6 +1494,7 @@ struct ExtensionPos : Extension<ExtensionPos>
 
 struct PosLookupSubTable
 {
+  friend struct Lookup;
   friend struct PosLookup;
 
   enum Type {
@@ -1412,10 +1510,9 @@ struct PosLookupSubTable
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:               return_trace (u.single.dispatch (c));
     case Pair:                 return_trace (u.pair.dispatch (c));
@@ -1432,7 +1529,6 @@ struct PosLookupSubTable
 
   protected:
   union {
-  HBUINT16             sub_format;
   SinglePos            single;
   PairPos              pair;
   CursivePos           cursive;
@@ -1444,34 +1540,39 @@ struct PosLookupSubTable
   ExtensionPos         extension;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct PosLookup : Lookup
 {
-  inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<PosLookupSubTable> (i); }
+  typedef struct PosLookupSubTable SubTable;
+
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
 
-  inline bool is_reverse (void) const
+  bool is_reverse () const
   {
     return false;
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    return_trace (dispatch (c));
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
   }
 
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { return dispatch (c); }
+
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
@@ -1480,21 +1581,18 @@ struct PosLookup : Lookup
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<PosLookupSubTable> (c); }
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    return_trace (dispatch (c));
-  }
-};
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
 
-typedef OffsetListOf<PosLookup> PosLookupList;
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
+};
 
 /*
  * GPOS -- Glyph Positioning
@@ -1503,22 +1601,25 @@ typedef OffsetListOf<PosLookup> PosLookupList;
 
 struct GPOS : GSUBGPOS
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_GPOS;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
 
-  inline const PosLookup& get_lookup (unsigned int i) const
+  const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<PosLookup> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<PosLookup> (c); }
+
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                  hb_face_t *face) const;
+
+  typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
 };
 
 
@@ -1548,7 +1649,10 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
   pos[j].attach_type() = type;
 }
 static void
-propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+                             unsigned int len,
+                             unsigned int i,
+                             hb_direction_t direction)
 {
   /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
    * offset of glyph they are attached to. */
@@ -1556,11 +1660,14 @@ propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direc
   if (likely (!chain))
     return;
 
+  pos[i].attach_chain() = 0;
+
   unsigned int j = (int) i + chain;
 
-  pos[i].attach_chain() = 0;
+  if (unlikely (j >= len))
+    return;
 
-  propagate_attachment_offsets (pos, j, direction);
+  propagate_attachment_offsets (pos, len, j, direction);
 
   assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
 
@@ -1599,7 +1706,7 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
 }
 
 void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
 {
   //_hb_buffer_assert_gsubgpos_vars (buffer);
 }
@@ -1616,24 +1723,25 @@ GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
   /* Handle attachments */
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
     for (unsigned int i = 0; i < len; i++)
-      propagate_attachment_offsets (pos, i, direction);
+      propagate_attachment_offsets (pos, len, i, direction);
 }
 
 
+struct GPOS_accelerator_t : GPOS::accelerator_t {};
+
+
 /* Out-of-class implementation for methods recursing */
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1645,10 +1753,6 @@ template <typename context_t>
 }
 
 
-#undef attach_chain
-#undef attach_type
-
-
 } /* namespace OT */
 
 
index bd72fe6..33b8f0e 100644 (file)
 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
 #define HB_OT_LAYOUT_GSUB_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
 
 
+static inline void SingleSubst_serialize (hb_serialize_context_t *c,
+                                         hb_array_t<const GlyphID> glyphs,
+                                         hb_array_t<const GlyphID> substitutes);
+
 struct SingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
-       c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
+       c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -65,18 +68,15 @@ struct SingleSubstFormat1
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -91,19 +91,37 @@ struct SingleSubstFormat1
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        unsigned int num_glyphs,
-                        int delta)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 int delta)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
+    deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    hb_codepoint_t delta = deltaGlyphID;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
@@ -122,27 +140,26 @@ struct SingleSubstFormat1
 
 struct SingleSubstFormat2
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-       c->glyphs->add (substitute[iter.get_coverage ()]);
+       c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -150,45 +167,57 @@ struct SingleSubstFormat2
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     if (unlikely (index >= substitute.len)) return_trace (false);
 
-    glyph_id = substitute[index];
-    c->replace_glyph (glyph_id);
+    c->replace_glyph (substitute[index]);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<GlyphID> &substitutes,
-                        unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
@@ -208,35 +237,35 @@ struct SingleSubstFormat2
 
 struct SingleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<GlyphID> &substitutes,
-                        unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 2;
     int delta = 0;
-    if (num_glyphs) {
+    if (glyphs.length)
+    {
       format = 1;
       /* TODO(serialize) check for wrap-around */
       delta = substitutes[0] - glyphs[0];
-      for (unsigned int i = 1; i < num_glyphs; i++)
-       if (delta != substitutes[i] - glyphs[i]) {
+      for (unsigned int i = 1; i < glyphs.length; i++)
+       if (delta != (int) (substitutes[i] - glyphs[i])) {
          format = 2;
          break;
        }
     }
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -255,24 +284,25 @@ struct SingleSubst
   } u;
 };
 
+static inline void
+SingleSubst_serialize (hb_serialize_context_t *c,
+                      hb_array_t<const GlyphID> glyphs,
+                      hb_array_t<const GlyphID> substitutes)
+{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
 
 struct Sequence
 {
-  inline void closure (hb_closure_context_t *c) const
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
     unsigned int count = substitute.len;
     for (unsigned int i = 0; i < count; i++)
-      c->glyphs->add (substitute[i]);
+      c->out->add (substitute[i]);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->output->add_array (substitute.arrayZ, substitute.len);
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (substitute.arrayZ, substitute.len); }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = substitute.len;
@@ -304,17 +334,14 @@ struct Sequence
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    return_trace (substitute.serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (substitute.sanitize (c));
@@ -329,12 +356,13 @@ struct Sequence
 
 struct MultipleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = sequence.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -343,27 +371,23 @@ struct MultipleSubstFormat1
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = sequence.len;
     for (unsigned int i = 0; i < count; i++)
-       (this+sequence[i]).collect_glyphs (c);
+      (this+sequence[i]).collect_glyphs (c);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -373,25 +397,33 @@ struct MultipleSubstFormat1
     return_trace ((this+sequence[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<unsigned int> &substitute_len_list,
-                        unsigned int num_glyphs,
-                        Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const unsigned int> substitute_len_list,
+                 hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
-                                                               substitute_glyphs_list,
-                                                               substitute_len_list[i]))) return_trace (false);
-    substitute_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int substitute_len = substitute_len_list[i];
+      if (unlikely (!sequence[i].serialize (c, this)
+                               .serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+       return_trace (false);
+      substitute_glyphs_list += substitute_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
@@ -411,24 +443,23 @@ struct MultipleSubstFormat1
 
 struct MultipleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<unsigned int> &substitute_len_list,
-                        unsigned int num_glyphs,
-                        Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const unsigned int> substitute_len_list,
+                 hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -445,103 +476,138 @@ struct MultipleSubst
   } u;
 };
 
+struct AlternateSet
+{
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = alternates.len;
+    for (unsigned int i = 0; i < count; i++)
+      c->out->add (alternates[i]);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int count = alternates.len;
+
+    if (unlikely (!count)) return_trace (false);
+
+    hb_mask_t glyph_mask = c->buffer->cur().mask;
+    hb_mask_t lookup_mask = c->lookup_mask;
+
+    /* Note: This breaks badly if two features enabled this lookup together. */
+    unsigned int shift = hb_ctz (lookup_mask);
+    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+    /* If alt_index is MAX, randomize feature if it is the rand feature. */
+    if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+      alt_index = c->random_number () % count + 1;
 
-typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
+    if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+    c->replace_glyph (alternates[alt_index - 1]);
+
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (alternates.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (alternates.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<GlyphID>
+               alternates;             /* Array of alternate GlyphIDs--in
                                         * arbitrary order */
+  public:
+  DEFINE_SIZE_ARRAY (2, alternates);
+};
 
 struct AlternateSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ())) {
-       const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-       unsigned int count = alt_set.len;
-       for (unsigned int i = 0; i < count; i++)
-         c->glyphs->add (alt_set[i]);
-      }
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+       (this+alternateSet[iter.get_coverage ()]).closure (c);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
-        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-      c->output->add_array (alt_set.arrayZ, alt_set.len);
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      (this+alternateSet[iter.get_coverage ()]).collect_glyphs (c);
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const AlternateSet &alt_set = this+alternateSet[index];
-
-    if (unlikely (!alt_set.len)) return_trace (false);
-
-    hb_mask_t glyph_mask = c->buffer->cur().mask;
-    hb_mask_t lookup_mask = c->lookup_mask;
-
-    /* Note: This breaks badly if two features enabled this lookup together. */
-    unsigned int shift = _hb_ctz (lookup_mask);
-    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
-    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
-
-    glyph_id = alt_set[alt_index - 1];
-
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
+    return_trace ((this+alternateSet[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<unsigned int> &alternate_len_list,
-                        unsigned int num_glyphs,
-                        Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const unsigned int> alternate_len_list,
+                 hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
-                                                                   alternate_glyphs_list,
-                                                                   alternate_len_list[i]))) return_trace (false);
-    alternate_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int alternate_len = alternate_len_list[i];
+      if (unlikely (!alternateSet[i].serialize (c, this)
+                                   .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+       return_trace (false);
+      alternate_glyphs_list += alternate_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
@@ -561,24 +627,23 @@ struct AlternateSubstFormat1
 
 struct AlternateSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &glyphs,
-                        Supplier<unsigned int> &alternate_len_list,
-                        unsigned int num_glyphs,
-                        Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> glyphs,
+                 hb_array_t<const unsigned int> alternate_len_list,
+                 hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,27 +663,34 @@ struct AlternateSubst
 
 struct Ligature
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
+    for (unsigned int i = 1; i < count; i++)
+      if (!glyphs->has (component[i]))
+        return false;
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = component.lenP1;
     for (unsigned int i = 1; i < count; i++)
       if (!c->glyphs->has (component[i]))
         return;
-    c->glyphs->add (ligGlyph);
+    c->out->add (ligGlyph);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0);
+    c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
     c->output->add (ligGlyph);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    if (c->len != component.len)
+    if (c->len != component.lenP1)
       return_trace (false);
 
     for (unsigned int i = 1; i < c->len; i++)
@@ -628,10 +700,10 @@ struct Ligature
     return_trace (true);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
 
     if (unlikely (!count)) return_trace (false);
 
@@ -643,7 +715,6 @@ struct Ligature
       return_trace (true);
     }
 
-    bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
 
     unsigned int match_length = 0;
@@ -655,7 +726,6 @@ struct Ligature
                              nullptr,
                              &match_length,
                              match_positions,
-                             &is_mark_ligature,
                              &total_component_count)))
       return_trace (false);
 
@@ -664,26 +734,24 @@ struct Ligature
                  match_positions,
                  match_length,
                  ligGlyph,
-                 is_mark_ligature,
                  total_component_count);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        GlyphID ligature,
-                        Supplier<GlyphID> &components, /* Starting from second */
-                        unsigned int num_components /* Including first component */)
+  bool serialize (hb_serialize_context_t *c,
+                 GlyphID ligature,
+                 hb_array_t<const GlyphID> components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
+    if (unlikely (!component.serialize (c, components))) return_trace (false);
     return_trace (true);
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
@@ -701,23 +769,30 @@ struct Ligature
 
 struct LigatureSet
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    unsigned int num_ligs = ligature.len;
+    for (unsigned int i = 0; i < num_ligs; i++)
+      if ((this+ligature[i]).intersects (glyphs))
+        return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).closure (c);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).collect_glyphs (c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -730,7 +805,7 @@ struct LigatureSet
     return_trace (false);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -743,26 +818,28 @@ struct LigatureSet
     return_trace (false);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &ligatures,
-                        Supplier<unsigned int> &component_count_list,
-                        unsigned int num_ligatures,
-                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> ligatures,
+                 hb_array_t<const unsigned int> component_count_list,
+                 hb_array_t<const GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
-    for (unsigned int i = 0; i < num_ligatures; i++)
-      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
-                                                               ligatures[i],
-                                                               component_list,
-                                                               component_count_list[i]))) return_trace (false);
-    ligatures += num_ligatures;
-    component_count_list += num_ligatures;
+    if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+    for (unsigned int i = 0; i < ligatures.length; i++)
+    {
+      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
+      if (unlikely (!ligature[i].serialize (c, this)
+                               .serialize (c,
+                                           ligatures[i],
+                                           component_list.sub_array (0, component_count))))
+       return_trace (false);
+      component_list += component_count;
+    }
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligature.sanitize (c, this));
@@ -778,12 +855,24 @@ struct LigatureSet
 
 struct LigatureSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    unsigned int count = ligatureSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+         (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -792,13 +881,11 @@ struct LigatureSubstFormat1
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -806,12 +893,9 @@ struct LigatureSubstFormat1
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
@@ -821,41 +905,49 @@ struct LigatureSubstFormat1
     return_trace (lig_set.would_apply (c));
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LigatureSet &lig_set = this+ligatureSet[index];
     return_trace (lig_set.apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &first_glyphs,
-                        Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                        unsigned int num_first_glyphs,
-                        Supplier<GlyphID> &ligatures_list,
-                        Supplier<unsigned int> &component_count_list,
-                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> first_glyphs,
+                 hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                 hb_array_t<const GlyphID> ligatures_list,
+                 hb_array_t<const unsigned int> component_count_list,
+                 hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_first_glyphs; i++)
-      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
-                                                                  ligatures_list,
-                                                                  component_count_list,
-                                                                  ligature_per_first_glyph_count_list[i],
-                                                                  component_list))) return_trace (false);
-    ligature_per_first_glyph_count_list += num_first_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < first_glyphs.length; i++)
+    {
+      unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+      if (unlikely (!ligatureSet[i].serialize (c, this)
+                                  .serialize (c,
+                                              ligatures_list.sub_array (0, ligature_count),
+                                              component_count_list.sub_array (0, ligature_count),
+                                              component_list))) return_trace (false);
+      ligatures_list += ligature_count;
+      component_count_list += ligature_count;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
@@ -875,13 +967,12 @@ struct LigatureSubstFormat1
 
 struct LigatureSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                        Supplier<GlyphID> &first_glyphs,
-                        Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                        unsigned int num_first_glyphs,
-                        Supplier<GlyphID> &ligatures_list,
-                        Supplier<unsigned int> &component_count_list,
-                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                 hb_array_t<const GlyphID> first_glyphs,
+                 hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                 hb_array_t<const GlyphID> ligatures_list,
+                 hb_array_t<const unsigned int> component_count_list,
+                 hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
@@ -891,7 +982,6 @@ struct LigatureSubst
     case 1: return_trace (u.format1.serialize (c,
                                               first_glyphs,
                                               ligature_per_first_glyph_count_list,
-                                              num_first_glyphs,
                                               ligatures_list,
                                               component_count_list,
                                               component_list));
@@ -900,7 +990,7 @@ struct LigatureSubst
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -924,17 +1014,38 @@ struct ChainContextSubst : ChainContext {};
 
 struct ExtensionSubst : Extension<ExtensionSubst>
 {
-  typedef struct SubstLookupSubTable LookupSubTable;
+  typedef struct SubstLookupSubTable SubTable;
 
-  inline bool is_reverse (void) const;
+  bool is_reverse () const;
 };
 
 
 struct ReverseChainSingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int count;
+
+    count = backtrack.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+backtrack[i]).intersects (glyphs))
+        return false;
+
+    count = lookahead.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+lookahead[i]).intersects (glyphs))
+        return false;
+
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
 
     unsigned int count;
@@ -950,20 +1061,18 @@ struct ReverseChainSingleSubstFormat1
         return;
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    Coverage::Iter iter;
     count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-       c->glyphs->add (substitute[iter.get_coverage ()]);
+       c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
 
     unsigned int count;
@@ -982,18 +1091,15 @@ struct ReverseChainSingleSubstFormat1
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
@@ -1026,7 +1132,14 @@ struct ReverseChainSingleSubstFormat1
     return_trace (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
@@ -1045,7 +1158,7 @@ struct ReverseChainSingleSubstFormat1
                                         * beginning of table */
   OffsetArrayOf<Coverage>
                backtrack;              /* Array of coverage tables
-                                        * in backtracking sequence, in  glyph
+                                        * in backtracking sequence, in glyph
                                         * sequence order */
   OffsetArrayOf<Coverage>
                lookaheadX;             /* Array of coverage tables
@@ -1061,7 +1174,7 @@ struct ReverseChainSingleSubstFormat1
 struct ReverseChainSingleSubst
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1086,6 +1199,7 @@ struct ReverseChainSingleSubst
 
 struct SubstLookupSubTable
 {
+  friend struct Lookup;
   friend struct SubstLookup;
 
   enum Type {
@@ -1100,10 +1214,9 @@ struct SubstLookupSubTable
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:               return_trace (u.single.dispatch (c));
     case Multiple:             return_trace (u.multiple.dispatch (c));
@@ -1119,7 +1232,6 @@ struct SubstLookupSubTable
 
   protected:
   union {
-  HBUINT16                     sub_format;
   SingleSubst                  single;
   MultipleSubst                        multiple;
   AlternateSubst               alternate;
@@ -1130,58 +1242,69 @@ struct SubstLookupSubTable
   ReverseChainSingleSubst      reverseChainContextSingle;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct SubstLookup : Lookup
 {
-  inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<SubstLookupSubTable> (i); }
+  typedef SubstLookupSubTable SubTable;
+
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
 
-  inline static bool lookup_type_is_reverse (unsigned int lookup_type)
-  { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
+  static bool lookup_type_is_reverse (unsigned int lookup_type)
+  { return lookup_type == SubTable::ReverseChainSingle; }
 
-  inline bool is_reverse (void) const
+  bool is_reverse () const
   {
     unsigned int type = get_type ();
-    if (unlikely (type == SubstLookupSubTable::Extension))
+    if (unlikely (type == SubTable::Extension))
       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
     return lookup_type_is_reverse (type);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
+  }
+
+  hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
   {
-    TRACE_CLOSURE (this);
     if (!c->should_visit_lookup (this_index))
-      return_trace (HB_VOID);
+      return hb_closure_context_t::default_return_value ();
 
     c->set_recurse_func (dispatch_closure_recurse_func);
-    return_trace (dispatch (c));
+
+    hb_closure_context_t::return_t ret = dispatch (c);
+
+    c->flush ();
+
+    return ret;
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
-    return_trace (dispatch (c));
+    return dispatch (c);
   }
 
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c,
-                          const hb_ot_layout_lookup_accelerator_t *accel) const
+  bool would_apply (hb_would_apply_context_t *c,
+                   const hb_ot_layout_lookup_accelerator_t *accel) const
   {
     TRACE_WOULD_APPLY (this);
     if (unlikely (!c->len))  return_trace (false);
@@ -1191,111 +1314,95 @@ struct SubstLookup : Lookup
 
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
-  inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
-                                                 unsigned int i)
-  { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
+  SubTable& serialize_subtable (hb_serialize_context_t *c,
+                                      unsigned int i)
+  { return get_subtables<SubTable> ()[i].serialize (c, this); }
 
-  inline bool serialize_single (hb_serialize_context_t *c,
-                               uint32_t lookup_props,
-                               Supplier<GlyphID> &glyphs,
-                               Supplier<GlyphID> &substitutes,
-                               unsigned int num_glyphs)
+  bool serialize_single (hb_serialize_context_t *c,
+                        uint32_t lookup_props,
+                        hb_array_t<const GlyphID> glyphs,
+                        hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
+    if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
   }
 
-  inline bool serialize_multiple (hb_serialize_context_t *c,
-                                 uint32_t lookup_props,
-                                 Supplier<GlyphID> &glyphs,
-                                 Supplier<unsigned int> &substitute_len_list,
-                                 unsigned int num_glyphs,
-                                 Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize_multiple (hb_serialize_context_t *c,
+                          uint32_t lookup_props,
+                          hb_array_t<const GlyphID> glyphs,
+                          hb_array_t<const unsigned int> substitute_len_list,
+                          hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
                                                                  glyphs,
                                                                  substitute_len_list,
-                                                                 num_glyphs,
                                                                  substitute_glyphs_list));
   }
 
-  inline bool serialize_alternate (hb_serialize_context_t *c,
-                                  uint32_t lookup_props,
-                                  Supplier<GlyphID> &glyphs,
-                                  Supplier<unsigned int> &alternate_len_list,
-                                  unsigned int num_glyphs,
-                                  Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize_alternate (hb_serialize_context_t *c,
+                           uint32_t lookup_props,
+                           hb_array_t<const GlyphID> glyphs,
+                           hb_array_t<const unsigned int> alternate_len_list,
+                           hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
                                                                   glyphs,
                                                                   alternate_len_list,
-                                                                  num_glyphs,
                                                                   alternate_glyphs_list));
   }
 
-  inline bool serialize_ligature (hb_serialize_context_t *c,
-                                 uint32_t lookup_props,
-                                 Supplier<GlyphID> &first_glyphs,
-                                 Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                                 unsigned int num_first_glyphs,
-                                 Supplier<GlyphID> &ligatures_list,
-                                 Supplier<unsigned int> &component_count_list,
-                                 Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize_ligature (hb_serialize_context_t *c,
+                          uint32_t lookup_props,
+                          hb_array_t<const GlyphID> first_glyphs,
+                          hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                          hb_array_t<const GlyphID> ligatures_list,
+                          hb_array_t<const unsigned int> component_count_list,
+                          hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
                                                                  first_glyphs,
                                                                  ligature_per_first_glyph_count_list,
-                                                                 num_first_glyphs,
                                                                  ligatures_list,
                                                                  component_count_list,
                                                                  component_list));
   }
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
-  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
+  static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
   {
     if (!c->should_visit_lookup (lookup_index))
       return HB_VOID;
-    return dispatch_recurse_func (c, lookup_index);
+
+    hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+
+    /* While in theory we should flush here, it will cause timeouts because a recursive
+     * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
+     * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+    //c->flush ();
+
+    return ret;
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubstLookupSubTable> (c); }
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    if (unlikely (!dispatch (c))) return_trace (false);
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
 
-    if (unlikely (get_type () == SubstLookupSubTable::Extension))
-    {
-      /* The spec says all subtables of an Extension lookup should
-       * have the same type, which shall not be the Extension type
-       * itself (but we already checked for that).
-       * This is specially important if one has a reverse type! */
-      unsigned int type = get_subtable (0).u.extension.get_type ();
-      unsigned int count = get_subtable_count ();
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable (i).u.extension.get_type () != type)
-         return_trace (false);
-    }
-    return_trace (true);
-  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
 };
 
-typedef OffsetListOf<SubstLookup> SubstLookupList;
-
 /*
  * GSUB -- Glyph Substitution
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
@@ -1303,61 +1410,47 @@ typedef OffsetListOf<SubstLookup> SubstLookupList;
 
 struct GSUB : GSUBGPOS
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_GSUB;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
 
-  inline const SubstLookup& get_lookup (unsigned int i) const
+  const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
-  static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<SubstLookup> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
-};
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<SubstLookup> (c); }
 
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                  hb_face_t *face) const;
 
-void
-GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
+  typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
+};
 
-  const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
-    buffer->info[i].syllable() = 0;
-  }
-}
+
+struct GSUB_accelerator_t : GSUB::accelerator_t {};
 
 
 /* Out-of-class implementation for methods recursing */
 
-/*static*/ inline bool ExtensionSubst::is_reverse (void) const
+/*static*/ inline bool ExtensionSubst::is_reverse () const
 {
   unsigned int type = get_type ();
-  if (unlikely (type == SubstLookupSubTable::Extension))
-    return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
+  if (unlikely (type == SubTable::Extension))
+    return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse ();
   return SubstLookup::lookup_type_is_reverse (type);
 }
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1368,7 +1461,6 @@ template <typename context_t>
   return ret;
 }
 
-
 } /* namespace OT */
 
 
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
deleted file mode 100644 (file)
index 661085d..0000000
+++ /dev/null
@@ -1,2394 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  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
- */
-
-#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-buffer-private.hh"
-#include "hb-map-private.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-set-private.hh"
-
-
-namespace OT {
-
-
-struct hb_closure_context_t :
-       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
-{
-  inline const char *get_name (void) { return "CLOSURE"; }
-  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-    return HB_VOID;
-  }
-
-  bool should_visit_lookup (unsigned int lookup_index)
-  {
-    if (is_lookup_done (lookup_index))
-      return false;
-    done_lookups->set (lookup_index, glyphs->get_population ());
-    return true;
-  }
-
-  bool is_lookup_done (unsigned int lookup_index)
-  {
-    // Have we visited this lookup with the current set of glyphs?
-    return done_lookups->get (lookup_index) == glyphs->get_population ();
-  }
-
-  hb_face_t *face;
-  hb_set_t *glyphs;
-  recurse_func_t recurse_func;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_closure_context_t (hb_face_t *face_,
-                       hb_set_t *glyphs_,
-                        hb_map_t *done_lookups_,
-                       unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                         face (face_),
-                         glyphs (glyphs_),
-                         recurse_func (nullptr),
-                         nesting_level_left (nesting_level_left_),
-                         debug_depth (0),
-                          done_lookups (done_lookups_) {}
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-
-  private:
-  hb_map_t *done_lookups;
-};
-
-
-struct hb_would_apply_context_t :
-       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
-{
-  inline const char *get_name (void) { return "WOULD_APPLY"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-
-  hb_face_t *face;
-  const hb_codepoint_t *glyphs;
-  unsigned int len;
-  bool zero_context;
-  unsigned int debug_depth;
-
-  hb_would_apply_context_t (hb_face_t *face_,
-                           const hb_codepoint_t *glyphs_,
-                           unsigned int len_,
-                           bool zero_context_) :
-                             face (face_),
-                             glyphs (glyphs_),
-                             len (len_),
-                             zero_context (zero_context_),
-                             debug_depth (0) {}
-};
-
-
-struct hb_collect_glyphs_context_t :
-       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
-{
-  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
-     * past the previous check.  For GSUB, we only want to collect the output
-     * glyphs in the recursion.  If output is not requested, we can go home now.
-     *
-     * Note further, that the above is not exactly correct.  A recursed lookup
-     * is allowed to match input that is not matched in the context, but that's
-     * not how most fonts are built.  It's possible to relax that and recurse
-     * with all sets here if it proves to be an issue.
-     */
-
-    if (output == hb_set_get_empty ())
-      return HB_VOID;
-
-    /* Return if new lookup was recursed to before. */
-    if (recursed_lookups->has (lookup_index))
-      return HB_VOID;
-
-    hb_set_t *old_before = before;
-    hb_set_t *old_input  = input;
-    hb_set_t *old_after  = after;
-    before = input = after = hb_set_get_empty ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-
-    before = old_before;
-    input  = old_input;
-    after  = old_after;
-
-    recursed_lookups->add (lookup_index);
-
-    return HB_VOID;
-  }
-
-  hb_face_t *face;
-  hb_set_t *before;
-  hb_set_t *input;
-  hb_set_t *after;
-  hb_set_t *output;
-  recurse_func_t recurse_func;
-  hb_set_t *recursed_lookups;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_collect_glyphs_context_t (hb_face_t *face_,
-                              hb_set_t  *glyphs_before, /* OUT. May be nullptr */
-                              hb_set_t  *glyphs_input,  /* OUT. May be nullptr */
-                              hb_set_t  *glyphs_after,  /* OUT. May be nullptr */
-                              hb_set_t  *glyphs_output, /* OUT. May be nullptr */
-                              unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                             face (face_),
-                             before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
-                             input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
-                             after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
-                             output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
-                             recurse_func (nullptr),
-                             recursed_lookups (nullptr),
-                             nesting_level_left (nesting_level_left_),
-                             debug_depth (0)
-  {
-    recursed_lookups = hb_set_create ();
-  }
-  ~hb_collect_glyphs_context_t (void)
-  {
-    hb_set_destroy (recursed_lookups);
-  }
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-};
-
-
-
-/* XXX Can we remove this? */
-
-template <typename set_t>
-struct hb_add_coverage_context_t :
-       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
-{
-  inline const char *get_name (void) { return "GET_COVERAGE"; }
-  typedef const Coverage &return_t;
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
-  static return_t default_return_value (void) { return Null(Coverage); }
-  bool stop_sublookup_iteration (return_t r) const
-  {
-    r.add_coverage (set);
-    return false;
-  }
-
-  hb_add_coverage_context_t (set_t *set_) :
-                           set (set_),
-                           debug_depth (0) {}
-
-  set_t *set;
-  unsigned int debug_depth;
-};
-
-
-struct hb_ot_apply_context_t :
-       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
-{
-  struct matcher_t
-  {
-    inline matcher_t (void) :
-            lookup_props (0),
-            ignore_zwnj (false),
-            ignore_zwj (false),
-            mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
-            syllable arg1(0),
-#undef arg1
-            match_func (nullptr),
-            match_data (nullptr) {};
-
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
-    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
-    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
-    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
-    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
-    inline void set_match_func (match_func_t match_func_,
-                               const void *match_data_)
-    { match_func = match_func_; match_data = match_data_; }
-
-    enum may_match_t {
-      MATCH_NO,
-      MATCH_YES,
-      MATCH_MAYBE
-    };
-
-    inline may_match_t may_match (const hb_glyph_info_t &info,
-                                 const HBUINT16          *glyph_data) const
-    {
-      if (!(info.mask & mask) ||
-         (syllable && syllable != info.syllable ()))
-       return MATCH_NO;
-
-      if (match_func)
-        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
-
-      return MATCH_MAYBE;
-    }
-
-    enum may_skip_t {
-      SKIP_NO,
-      SKIP_YES,
-      SKIP_MAYBE
-    };
-
-    inline may_skip_t
-    may_skip (const hb_ot_apply_context_t *c,
-             const hb_glyph_info_t    &info) const
-    {
-      if (!c->check_glyph_property (&info, lookup_props))
-       return SKIP_YES;
-
-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
-                   (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
-                   (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
-       return SKIP_MAYBE;
-
-      return SKIP_NO;
-    }
-
-    protected:
-    unsigned int lookup_props;
-    bool ignore_zwnj;
-    bool ignore_zwj;
-    hb_mask_t mask;
-    uint8_t syllable;
-    match_func_t match_func;
-    const void *match_data;
-  };
-
-  struct skipping_iterator_t
-  {
-    inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
-    {
-      c = c_;
-      match_glyph_data = nullptr;
-      matcher.set_match_func (nullptr, nullptr);
-      matcher.set_lookup_props (c->lookup_props);
-      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
-      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
-      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
-      matcher.set_ignore_zwj  (c->table_index == 1 || (context_match || c->auto_zwj));
-      matcher.set_mask (context_match ? -1 : c->lookup_mask);
-    }
-    inline void set_lookup_props (unsigned int lookup_props)
-    {
-      matcher.set_lookup_props (lookup_props);
-    }
-    inline void set_match_func (matcher_t::match_func_t match_func_,
-                               const void *match_data_,
-                               const HBUINT16 glyph_data[])
-    {
-      matcher.set_match_func (match_func_, match_data_);
-      match_glyph_data = glyph_data;
-    }
-
-    inline void reset (unsigned int start_index_,
-                      unsigned int num_items_)
-    {
-      idx = start_index_;
-      num_items = num_items_;
-      end = c->buffer->len;
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
-    }
-
-    inline void reject (void) { num_items++; match_glyph_data--; }
-
-    inline matcher_t::may_skip_t
-    may_skip (const hb_glyph_info_t    &info) const
-    {
-      return matcher.may_skip (c, info);
-    }
-
-    inline bool next (void)
-    {
-      assert (num_items > 0);
-      while (idx + num_items < end)
-      {
-       idx++;
-       const hb_glyph_info_t &info = c->buffer->info[idx];
-
-       matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-       if (unlikely (skip == matcher_t::SKIP_YES))
-         continue;
-
-       matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-       if (match == matcher_t::MATCH_YES ||
-           (match == matcher_t::MATCH_MAYBE &&
-            skip == matcher_t::SKIP_NO))
-       {
-         num_items--;
-         match_glyph_data++;
-         return true;
-       }
-
-       if (skip == matcher_t::SKIP_NO)
-         return false;
-      }
-      return false;
-    }
-    inline bool prev (void)
-    {
-      assert (num_items > 0);
-      while (idx >= num_items)
-      {
-       idx--;
-       const hb_glyph_info_t &info = c->buffer->out_info[idx];
-
-       matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-       if (unlikely (skip == matcher_t::SKIP_YES))
-         continue;
-
-       matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-       if (match == matcher_t::MATCH_YES ||
-           (match == matcher_t::MATCH_MAYBE &&
-            skip == matcher_t::SKIP_NO))
-       {
-         num_items--;
-         match_glyph_data++;
-         return true;
-       }
-
-       if (skip == matcher_t::SKIP_NO)
-         return false;
-      }
-      return false;
-    }
-
-    unsigned int idx;
-    protected:
-    hb_ot_apply_context_t *c;
-    matcher_t matcher;
-    const HBUINT16 *match_glyph_data;
-
-    unsigned int num_items;
-    unsigned int end;
-  };
-
-
-  inline const char *get_name (void) { return "APPLY"; }
-  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-  return_t recurse (unsigned int sub_lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
-      return default_return_value ();
-
-    nesting_level_left--;
-    bool ret = recurse_func (this, sub_lookup_index);
-    nesting_level_left++;
-    return ret;
-  }
-
-  skipping_iterator_t iter_input, iter_context;
-
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  recurse_func_t recurse_func;
-  const GDEF &gdef;
-  const VariationStore &var_store;
-
-  hb_direction_t direction;
-  hb_mask_t lookup_mask;
-  unsigned int table_index; /* GSUB/GPOS */
-  unsigned int lookup_index;
-  unsigned int lookup_props;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  bool auto_zwnj;
-  bool auto_zwj;
-  bool has_glyph_classes;
-
-
-  hb_ot_apply_context_t (unsigned int table_index_,
-                     hb_font_t *font_,
-                     hb_buffer_t *buffer_) :
-                       iter_input (), iter_context (),
-                       font (font_), face (font->face), buffer (buffer_),
-                       recurse_func (nullptr),
-                       gdef (*hb_ot_layout_from_face (face)->gdef),
-                       var_store (gdef.get_var_store ()),
-                       direction (buffer_->props.direction),
-                       lookup_mask (1),
-                       table_index (table_index_),
-                       lookup_index ((unsigned int) -1),
-                       lookup_props (0),
-                       nesting_level_left (HB_MAX_NESTING_LEVEL),
-                       debug_depth (0),
-                       auto_zwnj (true),
-                       auto_zwj (true),
-                       has_glyph_classes (gdef.has_glyph_classes ()) {}
-
-  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
-  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
-  inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
-  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-  inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
-  inline void set_lookup_props (unsigned int lookup_props_)
-  {
-    lookup_props = lookup_props_;
-    iter_input.init (this, false);
-    iter_context.init (this, true);
-  }
-
-  inline bool
-  match_properties_mark (hb_codepoint_t  glyph,
-                        unsigned int    glyph_props,
-                        unsigned int    match_props) const
-  {
-    /* If using mark filtering sets, the high short of
-     * match_props has the set index.
-     */
-    if (match_props & LookupFlag::UseMarkFilteringSet)
-      return gdef.mark_set_covers (match_props >> 16, glyph);
-
-    /* The second byte of match_props has the meaning
-     * "ignore marks of attachment type different than
-     * the attachment type specified."
-     */
-    if (match_props & LookupFlag::MarkAttachmentType)
-      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
-
-    return true;
-  }
-
-  inline bool
-  check_glyph_property (const hb_glyph_info_t *info,
-                       unsigned int  match_props) const
-  {
-    hb_codepoint_t glyph = info->codepoint;
-    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
-
-    /* Not covered, if, for example, glyph class is ligature and
-     * match_props includes LookupFlags::IgnoreLigatures
-     */
-    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
-      return false;
-
-    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (glyph, glyph_props, match_props);
-
-    return true;
-  }
-
-  inline void _set_glyph_props (hb_codepoint_t glyph_index,
-                         unsigned int class_guess = 0,
-                         bool ligature = false,
-                         bool component = false) const
-  {
-    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
-                         HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
-    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
-    if (ligature)
-    {
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
-      /* In the only place that the MULTIPLIED bit is used, Uniscribe
-       * seems to only care about the "last" transformation between
-       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
-       * and ligate again, it forgives the multiplication and acts as
-       * if only ligation happened.  As such, clear MULTIPLIED bit.
-       */
-      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    }
-    if (component)
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    if (likely (has_glyph_classes))
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
-    else if (class_guess)
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
-  }
-
-  inline void replace_glyph (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->cur().codepoint = glyph_index;
-  }
-  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
-                                          unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, true);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
-                                         unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, false, true);
-    buffer->output_glyph (glyph_index);
-  }
-};
-
-
-
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-struct ContextClosureFuncs
-{
-  intersects_func_t intersects;
-};
-struct ContextCollectGlyphsFuncs
-{
-  collect_glyphs_func_t collect;
-};
-struct ContextApplyFuncs
-{
-  match_func_t match;
-};
-
-
-static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyphs->has (value);
-}
-static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.intersects_class (glyphs, value);
-}
-static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).intersects (glyphs);
-}
-
-static inline bool intersects_array (hb_closure_context_t *c,
-                                    unsigned int count,
-                                    const HBUINT16 values[],
-                                    intersects_func_t intersects_func,
-                                    const void *intersects_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
-      return false;
-  return true;
-}
-
-
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  glyphs->add (value);
-}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  class_def.add_class (glyphs, value);
-}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  (data+coverage).add_coverage (glyphs);
-}
-static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
-                                 hb_set_t *glyphs,
-                                 unsigned int count,
-                                 const HBUINT16 values[],
-                                 collect_glyphs_func_t collect_func,
-                                 const void *collect_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    collect_func (glyphs, values[i], collect_data);
-}
-
-
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyph_id == value;
-}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.get_class (glyph_id) == value;
-}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
-}
-
-static inline bool would_match_input (hb_would_apply_context_t *c,
-                                     unsigned int count, /* Including the first glyph (not matched) */
-                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                     match_func_t match_func,
-                                     const void *match_data)
-{
-  if (count != c->len)
-    return false;
-
-  for (unsigned int i = 1; i < count; i++)
-    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
-      return false;
-
-  return true;
-}
-static inline bool match_input (hb_ot_apply_context_t *c,
-                               unsigned int count, /* Including the first glyph (not matched) */
-                               const HBUINT16 input[], /* Array of input values--start with second glyph */
-                               match_func_t match_func,
-                               const void *match_data,
-                               unsigned int *end_offset,
-                               unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
-                               bool *p_is_mark_ligature = nullptr,
-                               unsigned int *p_total_component_count = nullptr)
-{
-  TRACE_APPLY (nullptr);
-
-  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-  skippy_iter.reset (buffer->idx, count - 1);
-  skippy_iter.set_match_func (match_func, match_data, input);
-
-  /*
-   * This is perhaps the trickiest part of OpenType...  Remarks:
-   *
-   * - If all components of the ligature were marks, we call this a mark ligature.
-   *
-   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
-   *   it as a ligature glyph.
-   *
-   * - Ligatures cannot be formed across glyphs attached to different components
-   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
-   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
-   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
-   *   There are a couple of exceptions to this:
-   *
-   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
-   *     assuming that the font designer knows what they are doing (otherwise it can
-   *     break Indic stuff when a matra wants to ligate with a conjunct,
-   *
-   *   o If two marks want to ligate and they belong to different components of the
-   *     same ligature glyph, and said ligature glyph is to be ignored according to
-   *     mark-filtering rules, then allow.
-   *     https://github.com/harfbuzz/harfbuzz/issues/545
-   */
-
-  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
-
-  unsigned int total_component_count = 0;
-  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-
-  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-
-  enum {
-    LIGBASE_NOT_CHECKED,
-    LIGBASE_MAY_NOT_SKIP,
-    LIGBASE_MAY_SKIP
-  } ligbase = LIGBASE_NOT_CHECKED;
-
-  match_positions[0] = buffer->idx;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (!skippy_iter.next ()) return_trace (false);
-
-    match_positions[i] = skippy_iter.idx;
-
-    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
-    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
-
-    if (first_lig_id && first_lig_comp)
-    {
-      /* If first component was attached to a previous ligature component,
-       * all subsequent components should be attached to the same ligature
-       * component, otherwise we shouldn't ligate them... */
-      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-      {
-        /* ...unless, we are attached to a base ligature and that base
-        * ligature is ignorable. */
-        if (ligbase == LIGBASE_NOT_CHECKED)
-       {
-         bool found = false;
-         const hb_glyph_info_t *out = buffer->out_info;
-         unsigned int j = buffer->out_len;
-         while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
-         {
-           if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
-           {
-             j--;
-             found = true;
-             break;
-           }
-           j--;
-         }
-
-         if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
-           ligbase = LIGBASE_MAY_SKIP;
-         else
-           ligbase = LIGBASE_MAY_NOT_SKIP;
-       }
-
-        if (ligbase == LIGBASE_MAY_NOT_SKIP)
-         return_trace (false);
-      }
-    }
-    else
-    {
-      /* If first component was NOT attached to a previous ligature component,
-       * all subsequent components should also NOT be attached to any ligature
-       * component, unless they are attached to the first component itself! */
-      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
-       return_trace (false);
-    }
-
-    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
-    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
-  }
-
-  *end_offset = skippy_iter.idx - buffer->idx + 1;
-
-  if (p_is_mark_ligature)
-    *p_is_mark_ligature = is_mark_ligature;
-
-  if (p_total_component_count)
-    *p_total_component_count = total_component_count;
-
-  return_trace (true);
-}
-static inline bool ligate_input (hb_ot_apply_context_t *c,
-                                unsigned int count, /* Including the first glyph */
-                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                unsigned int match_length,
-                                hb_codepoint_t lig_glyph,
-                                bool is_mark_ligature,
-                                unsigned int total_component_count)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
-
-  /*
-   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
-   *   the ligature to keep its old ligature id.  This will allow it to attach to
-   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
-   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
-   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
-   *   later, we don't want them to lose their ligature id/component, otherwise
-   *   GPOS will fail to correctly position the mark ligature on top of the
-   *   LAM,LAM,HEH ligature.  See:
-   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
-   *
-   * - If a ligature is formed of components that some of which are also ligatures
-   *   themselves, and those ligature components had marks attached to *their*
-   *   components, we have to attach the marks to the new ligature component
-   *   positions!  Now *that*'s tricky!  And these marks may be following the
-   *   last component of the whole sequence, so we should loop forward looking
-   *   for them and update them.
-   *
-   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
-   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
-   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
-   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
-   *   the new ligature with a component value of 2.
-   *
-   *   This in fact happened to a font...  See:
-   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
-   */
-
-  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
-  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
-  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-  unsigned int components_so_far = last_num_components;
-
-  if (!is_mark_ligature)
-  {
-    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
-    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    {
-      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
-    }
-  }
-  c->replace_glyph_with_ligature (lig_glyph, klass);
-
-  for (unsigned int i = 1; i < count; i++)
-  {
-    while (buffer->idx < match_positions[i] && buffer->successful)
-    {
-      if (!is_mark_ligature) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-       if (this_comp == 0)
-         this_comp = last_num_components;
-       unsigned int new_lig_comp = components_so_far - last_num_components +
-                                   MIN (this_comp, last_num_components);
-         _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
-      }
-      buffer->next_glyph ();
-    }
-
-    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-    components_so_far += last_num_components;
-
-    /* Skip the base glyph */
-    buffer->idx++;
-  }
-
-  if (!is_mark_ligature && last_lig_id) {
-    /* Re-adjust components for any marks following. */
-    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
-      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
-       if (!this_comp)
-         break;
-       unsigned int new_lig_comp = components_so_far - last_num_components +
-                                   MIN (this_comp, last_num_components);
-       _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
-      } else
-       break;
-    }
-  }
-  return_trace (true);
-}
-
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
-                                   unsigned int count,
-                                   const HBUINT16 backtrack[],
-                                   match_func_t match_func,
-                                   const void *match_data,
-                                   unsigned int *match_start)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->backtrack_len (), count);
-  skippy_iter.set_match_func (match_func, match_data, backtrack);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.prev ())
-      return_trace (false);
-
-  *match_start = skippy_iter.idx;
-
-  return_trace (true);
-}
-
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
-                                   unsigned int count,
-                                   const HBUINT16 lookahead[],
-                                   match_func_t match_func,
-                                   const void *match_data,
-                                   unsigned int offset,
-                                   unsigned int *end_index)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->idx + offset - 1, count);
-  skippy_iter.set_match_func (match_func, match_data, lookahead);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.next ())
-      return_trace (false);
-
-  *end_index = skippy_iter.idx + 1;
-
-  return_trace (true);
-}
-
-
-
-struct LookupRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16     sequenceIndex;          /* Index into current glyph
-                                        * sequence--first glyph = 0 */
-  HBUINT16     lookupListIndex;        /* Lookup to apply to that
-                                        * position--zero--based */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-template <typename context_t>
-static inline void recurse_lookups (context_t *c,
-                                   unsigned int lookupCount,
-                                   const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
-{
-  for (unsigned int i = 0; i < lookupCount; i++)
-    c->recurse (lookupRecord[i].lookupListIndex);
-}
-
-static inline bool apply_lookup (hb_ot_apply_context_t *c,
-                                unsigned int count, /* Including the first glyph */
-                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                unsigned int lookupCount,
-                                const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
-                                unsigned int match_length)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-  int end;
-
-  /* All positions are distance from beginning of *output* buffer.
-   * Adjust. */
-  {
-    unsigned int bl = buffer->backtrack_len ();
-    end = bl + match_length;
-
-    int delta = bl - buffer->idx;
-    /* Convert positions to new indexing. */
-    for (unsigned int j = 0; j < count; j++)
-      match_positions[j] += delta;
-  }
-
-  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
-  {
-    unsigned int idx = lookupRecord[i].sequenceIndex;
-    if (idx >= count)
-      continue;
-
-    /* Don't recurse to ourself at same position.
-     * Note that this test is too naive, it doesn't catch longer loops. */
-    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
-      continue;
-
-    if (unlikely (!buffer->move_to (match_positions[idx])))
-      break;
-
-    if (unlikely (buffer->max_ops <= 0))
-      break;
-
-    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    if (!c->recurse (lookupRecord[i].lookupListIndex))
-      continue;
-
-    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    int delta = new_len - orig_len;
-
-    if (!delta)
-        continue;
-
-    /* Recursed lookup changed buffer len.  Adjust.
-     *
-     * TODO:
-     *
-     * Right now, if buffer length increased by n, we assume n new glyphs
-     * were added right after the current position, and if buffer length
-     * was decreased by n, we assume n match positions after the current
-     * one where removed.  The former (buffer length increased) case is
-     * fine, but the decrease case can be improved in at least two ways,
-     * both of which are significant:
-     *
-     *   - If recursed-to lookup is MultipleSubst and buffer length
-     *     decreased, then it's current match position that was deleted,
-     *     NOT the one after it.
-     *
-     *   - If buffer length was decreased by n, it does not necessarily
-     *     mean that n match positions where removed, as there might
-     *     have been marks and default-ignorables in the sequence.  We
-     *     should instead drop match positions between current-position
-     *     and current-position + n instead.
-     *
-     * It should be possible to construct tests for both of these cases.
-     */
-
-    end += delta;
-    if (end <= int (match_positions[idx]))
-    {
-      /* End might end up being smaller than match_positions[idx] if the recursed
-       * lookup ended up removing many items, more than we have had matched.
-       * Just never rewind end back and get out of here.
-       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
-      end = match_positions[idx];
-      /* There can't be any further changes. */
-      break;
-    }
-
-    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
-
-    if (delta > 0)
-    {
-      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
-       break;
-    }
-    else
-    {
-      /* NOTE: delta is negative. */
-      delta = MAX (delta, (int) next - (int) count);
-      next -= delta;
-    }
-
-    /* Shift! */
-    memmove (match_positions + next + delta, match_positions + next,
-            (count - next) * sizeof (match_positions[0]));
-    next += delta;
-    count += delta;
-
-    /* Fill in new entries. */
-    for (unsigned int j = idx + 1; j < next; j++)
-      match_positions[j] = match_positions[j - 1] + 1;
-
-    /* And fixup the rest. */
-    for (; next < count; next++)
-      match_positions[next] += delta;
-  }
-
-  buffer->move_to (end);
-
-  return_trace (true);
-}
-
-
-
-/* Contextual lookups */
-
-struct ContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data;
-};
-
-struct ContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data;
-};
-
-struct ContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data;
-};
-
-static inline void context_closure_lookup (hb_closure_context_t *c,
-                                          unsigned int inputCount, /* Including the first glyph (not matched) */
-                                          const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                          unsigned int lookupCount,
-                                          const LookupRecord lookupRecord[],
-                                          ContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                       inputCount ? inputCount - 1 : 0, input,
-                       lookup_context.funcs.intersects, lookup_context.intersects_data))
-    recurse_lookups (c,
-                    lookupCount, lookupRecord);
-}
-
-static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                 unsigned int lookupCount,
-                                                 const LookupRecord lookupRecord[],
-                                                 ContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->input,
-                inputCount ? inputCount - 1 : 0, input,
-                lookup_context.funcs.collect, lookup_context.collect_data);
-  recurse_lookups (c,
-                  lookupCount, lookupRecord);
-}
-
-static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
-                                              unsigned int inputCount, /* Including the first glyph (not matched) */
-                                              const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                              unsigned int lookupCount HB_UNUSED,
-                                              const LookupRecord lookupRecord[] HB_UNUSED,
-                                              ContextApplyLookupContext &lookup_context)
-{
-  return would_match_input (c,
-                           inputCount, input,
-                           lookup_context.funcs.match, lookup_context.match_data);
-}
-static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
-                                        unsigned int inputCount, /* Including the first glyph (not matched) */
-                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                        unsigned int lookupCount,
-                                        const LookupRecord lookupRecord[],
-                                        ContextApplyLookupContext &lookup_context)
-{
-  unsigned int match_length = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                     inputCount, input,
-                     lookup_context.funcs.match, lookup_context.match_data,
-                     &match_length, match_positions)
-      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
-         apply_lookup (c,
-                      inputCount, match_positions,
-                      lookupCount, lookupRecord,
-                      match_length));
-}
-
-struct Rule
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_closure_lookup (c,
-                           inputCount, inputZ,
-                           lookupCount, lookupRecord,
-                           lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_collect_glyphs_lookup (c,
-                                  inputCount, inputZ,
-                                  lookupCount, lookupRecord,
-                                  lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (inputCount.sanitize (c) &&
-                 lookupCount.sanitize (c) &&
-                 c->check_range (inputZ,
-                                 inputZ[0].static_size * inputCount +
-                                 LookupRecord::static_size * lookupCount));
-  }
-
-  protected:
-  HBUINT16     inputCount;             /* Total number of glyphs in input
-                                        * glyph sequence--includes the first
-                                        * glyph */
-  HBUINT16     lookupCount;            /* Number of LookupRecords */
-  HBUINT16     inputZ[VAR];            /* Array of match inputs--start with
-                                        * second glyph */
-/*LookupRecord lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                        * design order */
-  public:
-  DEFINE_SIZE_ARRAY (4, inputZ);
-};
-
-struct RuleSet
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Rule>
-               rule;                   /* Array of Rule tables
-                                        * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-
-struct ContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-
-    const Coverage &cov = (this+coverage);
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-       const RuleSet &rule_set = this+ruleSet[i];
-       rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED))
-      return_trace (false);
-
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-               coverage;               /* Offset to Coverage table--from
-                                        * beginning of table */
-  OffsetArrayOf<RuleSet>
-               ruleSet;                /* Array of RuleSet tables
-                                        * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-
-struct ContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &class_def = this+classDef;
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (class_def.intersects_class (c->glyphs, i)) {
-       const RuleSet &rule_set = this+ruleSet[i];
-       rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &class_def = this+classDef;
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &class_def = this+classDef;
-    unsigned int index = class_def.get_class (c->glyphs[0]);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &class_def = this+classDef;
-    index = class_def.get_class (c->buffer->cur().codepoint);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-               coverage;               /* Offset to Coverage table--from
-                                        * beginning of table */
-  OffsetTo<ClassDef>
-               classDef;               /* Offset to glyph ClassDef table--from
-                                        * beginning of table */
-  OffsetArrayOf<RuleSet>
-               ruleSet;                /* Array of RuleSet tables
-                                        * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (8, ruleSet);
-};
-
-
-struct ContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverageZ[0]).intersects (c->glyphs))
-      return;
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      this
-    };
-    context_closure_lookup (c,
-                           glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                           lookupCount, lookupRecord,
-                           lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverageZ[0]).add_coverage (c->input);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      this
-    };
-
-    context_collect_glyphs_lookup (c,
-                                  glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                                  lookupCount, lookupRecord,
-                                  lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverageZ[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
-    unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
-    return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 3 */
-  HBUINT16     glyphCount;             /* Number of glyphs in the input glyph
-                                        * sequence */
-  HBUINT16     lookupCount;            /* Number of LookupRecords */
-  OffsetTo<Coverage>
-               coverageZ[VAR];         /* Array of offsets to Coverage
-                                        * table in glyph sequence order */
-/*LookupRecord lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                        * design order */
-  public:
-  DEFINE_SIZE_ARRAY (6, coverageZ);
-};
-
-struct Context
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  ContextFormat1       format1;
-  ContextFormat2       format2;
-  ContextFormat3       format3;
-  } u;
-};
-
-
-/* Chaining Contextual lookups */
-
-struct ChainContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data[3];
-};
-
-struct ChainContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data[3];
-};
-
-struct ChainContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data[3];
-};
-
-static inline void chain_context_closure_lookup (hb_closure_context_t *c,
-                                                unsigned int backtrackCount,
-                                                const HBUINT16 backtrack[],
-                                                unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                unsigned int lookaheadCount,
-                                                const HBUINT16 lookahead[],
-                                                unsigned int lookupCount,
-                                                const LookupRecord lookupRecord[],
-                                                ChainContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                       backtrackCount, backtrack,
-                       lookup_context.funcs.intersects, lookup_context.intersects_data[0])
-   && intersects_array (c,
-                       inputCount ? inputCount - 1 : 0, input,
-                       lookup_context.funcs.intersects, lookup_context.intersects_data[1])
-   && intersects_array (c,
-                      lookaheadCount, lookahead,
-                      lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
-    recurse_lookups (c,
-                    lookupCount, lookupRecord);
-}
-
-static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                       unsigned int backtrackCount,
-                                                       const HBUINT16 backtrack[],
-                                                       unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                       unsigned int lookaheadCount,
-                                                       const HBUINT16 lookahead[],
-                                                       unsigned int lookupCount,
-                                                       const LookupRecord lookupRecord[],
-                                                       ChainContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->before,
-                backtrackCount, backtrack,
-                lookup_context.funcs.collect, lookup_context.collect_data[0]);
-  collect_array (c, c->input,
-                inputCount ? inputCount - 1 : 0, input,
-                lookup_context.funcs.collect, lookup_context.collect_data[1]);
-  collect_array (c, c->after,
-                lookaheadCount, lookahead,
-                lookup_context.funcs.collect, lookup_context.collect_data[2]);
-  recurse_lookups (c,
-                  lookupCount, lookupRecord);
-}
-
-static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
-                                                    unsigned int backtrackCount,
-                                                    const HBUINT16 backtrack[] HB_UNUSED,
-                                                    unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                    const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                    unsigned int lookaheadCount,
-                                                    const HBUINT16 lookahead[] HB_UNUSED,
-                                                    unsigned int lookupCount HB_UNUSED,
-                                                    const LookupRecord lookupRecord[] HB_UNUSED,
-                                                    ChainContextApplyLookupContext &lookup_context)
-{
-  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
-      && would_match_input (c,
-                           inputCount, input,
-                           lookup_context.funcs.match, lookup_context.match_data[1]);
-}
-
-static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
-                                              unsigned int backtrackCount,
-                                              const HBUINT16 backtrack[],
-                                              unsigned int inputCount, /* Including the first glyph (not matched) */
-                                              const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                              unsigned int lookaheadCount,
-                                              const HBUINT16 lookahead[],
-                                              unsigned int lookupCount,
-                                              const LookupRecord lookupRecord[],
-                                              ChainContextApplyLookupContext &lookup_context)
-{
-  unsigned int start_index = 0, match_length = 0, end_index = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                     inputCount, input,
-                     lookup_context.funcs.match, lookup_context.match_data[1],
-                     &match_length, match_positions)
-      && match_backtrack (c,
-                         backtrackCount, backtrack,
-                         lookup_context.funcs.match, lookup_context.match_data[0],
-                         &start_index)
-      && match_lookahead (c,
-                         lookaheadCount, lookahead,
-                         lookup_context.funcs.match, lookup_context.match_data[2],
-                         match_length, &end_index)
-      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
-          apply_lookup (c,
-                      inputCount, match_positions,
-                      lookupCount, lookupRecord,
-                      match_length));
-}
-
-struct ChainRule
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_closure_lookup (c,
-                                 backtrack.len, backtrack.arrayZ,
-                                 input.len, input.arrayZ,
-                                 lookahead.len, lookahead.arrayZ,
-                                 lookup.len, lookup.arrayZ,
-                                 lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_collect_glyphs_lookup (c,
-                                        backtrack.len, backtrack.arrayZ,
-                                        input.len, input.arrayZ,
-                                        lookahead.len, lookahead.arrayZ,
-                                        lookup.len, lookup.arrayZ,
-                                        lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_would_apply_lookup (c,
-                                                   backtrack.len, backtrack.arrayZ,
-                                                   input.len, input.arrayZ,
-                                                   lookahead.len, lookahead.arrayZ, lookup.len,
-                                                   lookup.arrayZ, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_apply_lookup (c,
-                                             backtrack.len, backtrack.arrayZ,
-                                             input.len, input.arrayZ,
-                                             lookahead.len, lookahead.arrayZ, lookup.len,
-                                             lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  ArrayOf<HBUINT16>
-               backtrack;              /* Array of backtracking values
-                                        * (to be matched before the input
-                                        * sequence) */
-  HeadlessArrayOf<HBUINT16>
-               inputX;                 /* Array of input values (start with
-                                        * second glyph) */
-  ArrayOf<HBUINT16>
-               lookaheadX;             /* Array of lookahead values's (to be
-                                        * matched after the input sequence) */
-  ArrayOf<LookupRecord>
-               lookupX;                /* Array of LookupRecords--in
-                                        * design order) */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-struct ChainRuleSet
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<ChainRule>
-               rule;                   /* Array of ChainRule tables
-                                        * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-struct ChainContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const Coverage &cov = (this+coverage);
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-       const ChainRuleSet &rule_set = this+ruleSet[i];
-       rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-               coverage;               /* Offset to Coverage table--from
-                                        * beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-               ruleSet;                /* Array of ChainRuleSet tables
-                                        * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-struct ChainContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (input_class_def.intersects_class (c->glyphs, i)) {
-       const ChainRuleSet &rule_set = this+ruleSet[i];
-       rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    unsigned int index = input_class_def.get_class (c->glyphs[0]);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    index = input_class_def.get_class (c->buffer->cur().codepoint);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) &&
-                 backtrackClassDef.sanitize (c, this) &&
-                 inputClassDef.sanitize (c, this) &&
-                 lookaheadClassDef.sanitize (c, this) &&
-                 ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-               coverage;               /* Offset to Coverage table--from
-                                        * beginning of table */
-  OffsetTo<ClassDef>
-               backtrackClassDef;      /* Offset to glyph ClassDef table
-                                        * containing backtrack sequence
-                                        * data--from beginning of table */
-  OffsetTo<ClassDef>
-               inputClassDef;          /* Offset to glyph ClassDef
-                                        * table containing input sequence
-                                        * data--from beginning of table */
-  OffsetTo<ClassDef>
-               lookaheadClassDef;      /* Offset to glyph ClassDef table
-                                        * containing lookahead sequence
-                                        * data--from beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-               ruleSet;                /* Array of ChainRuleSet tables
-                                        * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (12, ruleSet);
-};
-
-struct ChainContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    if (!(this+input[0]).intersects (c->glyphs))
-      return;
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      {this, this, this}
-    };
-    chain_context_closure_lookup (c,
-                                 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                 input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                 lookup.len, lookup.arrayZ,
-                                 lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    (this+input[0]).add_coverage (c->input);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      {this, this, this}
-    };
-    chain_context_collect_glyphs_lookup (c,
-                                        backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                        input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                        lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                        lookup.len, lookup.arrayZ,
-                                        lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_would_apply_lookup (c,
-                                                   backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                                   input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                                   lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                                   lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    return this+input[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_apply_lookup (c,
-                                             backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                             input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                             lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                             lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!input.sanitize (c, this)) return_trace (false);
-    if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier--format = 3 */
-  OffsetArrayOf<Coverage>
-               backtrack;              /* Array of coverage tables
-                                        * in backtracking sequence, in  glyph
-                                        * sequence order */
-  OffsetArrayOf<Coverage>
-               inputX          ;       /* Array of coverage
-                                        * tables in input sequence, in glyph
-                                        * sequence order */
-  OffsetArrayOf<Coverage>
-               lookaheadX;             /* Array of coverage tables
-                                        * in lookahead sequence, in glyph
-                                        * sequence order */
-  ArrayOf<LookupRecord>
-               lookupX;                /* Array of LookupRecords--in
-                                        * design order) */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-struct ChainContext
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format; /* Format identifier */
-  ChainContextFormat1  format1;
-  ChainContextFormat2  format2;
-  ChainContextFormat3  format3;
-  } u;
-};
-
-
-template <typename T>
-struct ExtensionFormat1
-{
-  inline unsigned int get_type (void) const { return extensionLookupType; }
-
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    unsigned int offset = extensionOffset;
-    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
-    return StructAtOffset<typename T::LookupSubTable> (this, offset);
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
-    return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
-  }
-
-  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                 extensionOffset != 0 &&
-                 extensionLookupType != T::LookupSubTable::Extension);
-  }
-
-  protected:
-  HBUINT16     format;                 /* Format identifier. Set to 1. */
-  HBUINT16     extensionLookupType;    /* Lookup type of subtable referenced
-                                        * by ExtensionOffset (i.e. the
-                                        * extension subtable). */
-  HBUINT32     extensionOffset;        /* Offset to the extension subtable,
-                                        * of lookup type subtable. */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename T>
-struct Extension
-{
-  inline unsigned int get_type (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_type ();
-    default:return 0;
-    }
-  }
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
-    default:return Null(typename T::LookupSubTable);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16             format;         /* Format identifier */
-  ExtensionFormat1<T>  format1;
-  } u;
-};
-
-
-/*
- * GSUB/GPOS Common
- */
-
-struct GSUBGPOS
-{
-  inline unsigned int get_script_count (void) const
-  { return (this+scriptList).len; }
-  inline const Tag& get_script_tag (unsigned int i) const
-  { return (this+scriptList).get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                      unsigned int *script_count /* IN/OUT */,
-                                      hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
-  inline const Script& get_script (unsigned int i) const
-  { return (this+scriptList)[i]; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+scriptList).find_index (tag, index); }
-
-  inline unsigned int get_feature_count (void) const
-  { return (this+featureList).len; }
-  inline hb_tag_t get_feature_tag (unsigned int i) const
-  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
-  inline unsigned int get_feature_tags (unsigned int start_offset,
-                                       unsigned int *feature_count /* IN/OUT */,
-                                       hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
-  inline const Feature& get_feature (unsigned int i) const
-  { return (this+featureList)[i]; }
-  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+featureList).find_index (tag, index); }
-
-  inline unsigned int get_lookup_count (void) const
-  { return (this+lookupList).len; }
-  inline const Lookup& get_lookup (unsigned int i) const
-  { return (this+lookupList)[i]; }
-
-  inline bool find_variations_index (const int *coords, unsigned int num_coords,
-                                    unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-          .find_index (coords, num_coords, index); }
-  inline const Feature& get_feature_variation (unsigned int feature_index,
-                                              unsigned int variations_index) const
-  {
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-       version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-                                                                  feature_index);
-      if (feature)
-        return *feature;
-    }
-    return get_feature (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                 likely (version.major == 1) &&
-                 scriptList.sanitize (c, this) &&
-                 featureList.sanitize (c, this) &&
-                 lookupList.sanitize (c, this) &&
-                 (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-  }
-
-  protected:
-  FixedVersion<>version;       /* Version of the GSUB/GPOS table--initially set
-                                * to 0x00010000u */
-  OffsetTo<ScriptList>
-               scriptList;     /* ScriptList table */
-  OffsetTo<FeatureList>
-               featureList;    /* FeatureList table */
-  OffsetTo<LookupList>
-               lookupList;     /* LookupList table */
-  LOffsetTo<FeatureVariations>
-               featureVars;    /* Offset to Feature Variations
-                                  table--from beginning of table
-                                * (may be NULL).  Introduced
-                                * in version 0x00010001. */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
new file mode 100644 (file)
index 0000000..88d834d
--- /dev/null
@@ -0,0 +1,2779 @@
+/*
+ * Copyright © 2007,2008,2009,2010  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
+ */
+
+#ifndef HB_OT_LAYOUT_GSUBGPOS_HH
+#define HB_OT_LAYOUT_GSUBGPOS_HH
+
+#include "hb.hh"
+#include "hb-buffer.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
+
+
+namespace OT {
+
+
+struct hb_intersects_context_t :
+       hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
+{
+  const char *get_name () { return "INTERSECTS"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_set_t *glyphs;
+  unsigned int debug_depth;
+
+  hb_intersects_context_t (const hb_set_t *glyphs_) :
+                            glyphs (glyphs_),
+                            debug_depth (0) {}
+};
+
+struct hb_closure_context_t :
+       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "CLOSURE"; }
+  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+  }
+
+  bool should_visit_lookup (unsigned int lookup_index)
+  {
+    if (is_lookup_done (lookup_index))
+      return false;
+    done_lookups->set (lookup_index, glyphs->get_population ());
+    return true;
+  }
+
+  bool is_lookup_done (unsigned int lookup_index)
+  {
+    /* Have we visited this lookup with the current set of glyphs? */
+    return done_lookups->get (lookup_index) == glyphs->get_population ();
+  }
+
+  hb_face_t *face;
+  hb_set_t *glyphs;
+  hb_set_t out[1];
+  recurse_func_t recurse_func;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_closure_context_t (hb_face_t *face_,
+                       hb_set_t *glyphs_,
+                       hb_map_t *done_lookups_,
+                       unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                         face (face_),
+                         glyphs (glyphs_),
+                         recurse_func (nullptr),
+                         nesting_level_left (nesting_level_left_),
+                         debug_depth (0),
+                         done_lookups (done_lookups_) {}
+
+  ~hb_closure_context_t () { flush (); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+
+  void flush ()
+  {
+    hb_set_union (glyphs, out);
+    hb_set_clear (out);
+  }
+
+  private:
+  hb_map_t *done_lookups;
+};
+
+
+struct hb_would_apply_context_t :
+       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
+{
+  const char *get_name () { return "WOULD_APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.would_apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  hb_face_t *face;
+  const hb_codepoint_t *glyphs;
+  unsigned int len;
+  bool zero_context;
+  unsigned int debug_depth;
+
+  hb_would_apply_context_t (hb_face_t *face_,
+                           const hb_codepoint_t *glyphs_,
+                           unsigned int len_,
+                           bool zero_context_) :
+                             face (face_),
+                             glyphs (glyphs_),
+                             len (len_),
+                             zero_context (zero_context_),
+                             debug_depth (0) {}
+};
+
+
+struct hb_collect_glyphs_context_t :
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "COLLECT_GLYPHS"; }
+  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
+     * past the previous check.  For GSUB, we only want to collect the output
+     * glyphs in the recursion.  If output is not requested, we can go home now.
+     *
+     * Note further, that the above is not exactly correct.  A recursed lookup
+     * is allowed to match input that is not matched in the context, but that's
+     * not how most fonts are built.  It's possible to relax that and recurse
+     * with all sets here if it proves to be an issue.
+     */
+
+    if (output == hb_set_get_empty ())
+      return;
+
+    /* Return if new lookup was recursed to before. */
+    if (recursed_lookups->has (lookup_index))
+      return;
+
+    hb_set_t *old_before = before;
+    hb_set_t *old_input  = input;
+    hb_set_t *old_after  = after;
+    before = input = after = hb_set_get_empty ();
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+
+    before = old_before;
+    input  = old_input;
+    after  = old_after;
+
+    recursed_lookups->add (lookup_index);
+  }
+
+  hb_face_t *face;
+  hb_set_t *before;
+  hb_set_t *input;
+  hb_set_t *after;
+  hb_set_t *output;
+  recurse_func_t recurse_func;
+  hb_set_t *recursed_lookups;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_collect_glyphs_context_t (hb_face_t *face_,
+                              hb_set_t  *glyphs_before, /* OUT.  May be NULL */
+                              hb_set_t  *glyphs_input,  /* OUT.  May be NULL */
+                              hb_set_t  *glyphs_after,  /* OUT.  May be NULL */
+                              hb_set_t  *glyphs_output, /* OUT.  May be NULL */
+                              unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                             face (face_),
+                             before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
+                             input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
+                             after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
+                             output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
+                             recurse_func (nullptr),
+                             recursed_lookups (hb_set_create ()),
+                             nesting_level_left (nesting_level_left_),
+                             debug_depth (0) {}
+  ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+};
+
+
+
+template <typename set_t>
+struct hb_add_coverage_context_t :
+       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
+{
+  const char *get_name () { return "GET_COVERAGE"; }
+  typedef const Coverage &return_t;
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.get_coverage (); }
+  static return_t default_return_value () { return Null(Coverage); }
+  bool stop_sublookup_iteration (return_t r) const
+  {
+    r.add_coverage (set);
+    return false;
+  }
+
+  hb_add_coverage_context_t (set_t *set_) :
+                           set (set_),
+                           debug_depth (0) {}
+
+  set_t *set;
+  unsigned int debug_depth;
+};
+
+
+struct hb_ot_apply_context_t :
+       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  struct matcher_t
+  {
+    matcher_t () :
+            lookup_props (0),
+            ignore_zwnj (false),
+            ignore_zwj (false),
+            mask (-1),
+#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
+            syllable arg1(0),
+#undef arg1
+            match_func (nullptr),
+            match_data (nullptr) {}
+
+    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+    void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
+    void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
+    void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
+    void set_mask (hb_mask_t mask_) { mask = mask_; }
+    void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
+    void set_match_func (match_func_t match_func_,
+                               const void *match_data_)
+    { match_func = match_func_; match_data = match_data_; }
+
+    enum may_match_t {
+      MATCH_NO,
+      MATCH_YES,
+      MATCH_MAYBE
+    };
+
+    may_match_t may_match (const hb_glyph_info_t &info,
+                                 const HBUINT16        *glyph_data) const
+    {
+      if (!(info.mask & mask) ||
+         (syllable && syllable != info.syllable ()))
+       return MATCH_NO;
+
+      if (match_func)
+       return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+
+      return MATCH_MAYBE;
+    }
+
+    enum may_skip_t {
+      SKIP_NO,
+      SKIP_YES,
+      SKIP_MAYBE
+    };
+
+    may_skip_t may_skip (const hb_ot_apply_context_t *c,
+                        const hb_glyph_info_t       &info) const
+    {
+      if (!c->check_glyph_property (&info, lookup_props))
+       return SKIP_YES;
+
+      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
+                   (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
+                   (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
+       return SKIP_MAYBE;
+
+      return SKIP_NO;
+    }
+
+    protected:
+    unsigned int lookup_props;
+    bool ignore_zwnj;
+    bool ignore_zwj;
+    hb_mask_t mask;
+    uint8_t syllable;
+    match_func_t match_func;
+    const void *match_data;
+  };
+
+  struct skipping_iterator_t
+  {
+    void init (hb_ot_apply_context_t *c_, bool context_match = false)
+    {
+      c = c_;
+      match_glyph_data = nullptr;
+      matcher.set_match_func (nullptr, nullptr);
+      matcher.set_lookup_props (c->lookup_props);
+      /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
+      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
+      /* Ignore ZWJ if we are matching context, or asked to. */
+      matcher.set_ignore_zwj  (context_match || c->auto_zwj);
+      matcher.set_mask (context_match ? -1 : c->lookup_mask);
+    }
+    void set_lookup_props (unsigned int lookup_props)
+    {
+      matcher.set_lookup_props (lookup_props);
+    }
+    void set_match_func (matcher_t::match_func_t match_func_,
+                        const void *match_data_,
+                        const HBUINT16 glyph_data[])
+    {
+      matcher.set_match_func (match_func_, match_data_);
+      match_glyph_data = glyph_data;
+    }
+
+    void reset (unsigned int start_index_,
+                      unsigned int num_items_)
+    {
+      idx = start_index_;
+      num_items = num_items_;
+      end = c->buffer->len;
+      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
+    }
+
+    void reject () { num_items++; match_glyph_data--; }
+
+    matcher_t::may_skip_t
+    may_skip (const hb_glyph_info_t &info) const
+    { return matcher.may_skip (c, info); }
+
+    bool next ()
+    {
+      assert (num_items > 0);
+      while (idx + num_items < end)
+      {
+       idx++;
+       const hb_glyph_info_t &info = c->buffer->info[idx];
+
+       matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+       if (unlikely (skip == matcher_t::SKIP_YES))
+         continue;
+
+       matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+       if (match == matcher_t::MATCH_YES ||
+           (match == matcher_t::MATCH_MAYBE &&
+            skip == matcher_t::SKIP_NO))
+       {
+         num_items--;
+         match_glyph_data++;
+         return true;
+       }
+
+       if (skip == matcher_t::SKIP_NO)
+         return false;
+      }
+      return false;
+    }
+    bool prev ()
+    {
+      assert (num_items > 0);
+      while (idx > num_items - 1)
+      {
+       idx--;
+       const hb_glyph_info_t &info = c->buffer->out_info[idx];
+
+       matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+       if (unlikely (skip == matcher_t::SKIP_YES))
+         continue;
+
+       matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+       if (match == matcher_t::MATCH_YES ||
+           (match == matcher_t::MATCH_MAYBE &&
+            skip == matcher_t::SKIP_NO))
+       {
+         num_items--;
+         match_glyph_data++;
+         return true;
+       }
+
+       if (skip == matcher_t::SKIP_NO)
+         return false;
+      }
+      return false;
+    }
+
+    unsigned int idx;
+    protected:
+    hb_ot_apply_context_t *c;
+    matcher_t matcher;
+    const HBUINT16 *match_glyph_data;
+
+    unsigned int num_items;
+    unsigned int end;
+  };
+
+
+  const char *get_name () { return "APPLY"; }
+  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+  return_t recurse (unsigned int sub_lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+      return default_return_value ();
+
+    nesting_level_left--;
+    bool ret = recurse_func (this, sub_lookup_index);
+    nesting_level_left++;
+    return ret;
+  }
+
+  skipping_iterator_t iter_input, iter_context;
+
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  recurse_func_t recurse_func;
+  const GDEF &gdef;
+  const VariationStore &var_store;
+
+  hb_direction_t direction;
+  hb_mask_t lookup_mask;
+  unsigned int table_index; /* GSUB/GPOS */
+  unsigned int lookup_index;
+  unsigned int lookup_props;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  bool has_glyph_classes;
+  bool auto_zwnj;
+  bool auto_zwj;
+  bool random;
+
+  uint32_t random_state;
+
+
+  hb_ot_apply_context_t (unsigned int table_index_,
+                     hb_font_t *font_,
+                     hb_buffer_t *buffer_) :
+                       iter_input (), iter_context (),
+                       font (font_), face (font->face), buffer (buffer_),
+                       recurse_func (nullptr),
+                       gdef (*face->table.GDEF->table),
+                       var_store (gdef.get_var_store ()),
+                       direction (buffer_->props.direction),
+                       lookup_mask (1),
+                       table_index (table_index_),
+                       lookup_index ((unsigned int) -1),
+                       lookup_props (0),
+                       nesting_level_left (HB_MAX_NESTING_LEVEL),
+                       debug_depth (0),
+                       has_glyph_classes (gdef.has_glyph_classes ()),
+                       auto_zwnj (true),
+                       auto_zwj (true),
+                       random (false),
+                       random_state (1) { init_iters (); }
+
+  void init_iters ()
+  {
+    iter_input.init (this, false);
+    iter_context.init (this, true);
+  }
+
+  void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
+  void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
+  void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+  void set_random (bool random_) { random = random_; }
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+  void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
+  void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
+
+  uint32_t random_number ()
+  {
+    /* http://www.cplusplus.com/reference/random/minstd_rand/ */
+    random_state = random_state * 48271 % 2147483647;
+    return random_state;
+  }
+
+  bool match_properties_mark (hb_codepoint_t  glyph,
+                             unsigned int    glyph_props,
+                             unsigned int    match_props) const
+  {
+    /* If using mark filtering sets, the high short of
+     * match_props has the set index.
+     */
+    if (match_props & LookupFlag::UseMarkFilteringSet)
+      return gdef.mark_set_covers (match_props >> 16, glyph);
+
+    /* The second byte of match_props has the meaning
+     * "ignore marks of attachment type different than
+     * the attachment type specified."
+     */
+    if (match_props & LookupFlag::MarkAttachmentType)
+      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
+
+    return true;
+  }
+
+  bool check_glyph_property (const hb_glyph_info_t *info,
+                            unsigned int  match_props) const
+  {
+    hb_codepoint_t glyph = info->codepoint;
+    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
+
+    /* Not covered, if, for example, glyph class is ligature and
+     * match_props includes LookupFlags::IgnoreLigatures
+     */
+    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
+      return false;
+
+    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
+      return match_properties_mark (glyph, glyph_props, match_props);
+
+    return true;
+  }
+
+  void _set_glyph_props (hb_codepoint_t glyph_index,
+                         unsigned int class_guess = 0,
+                         bool ligature = false,
+                         bool component = false) const
+  {
+    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
+                         HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
+    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
+    if (ligature)
+    {
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+      /* In the only place that the MULTIPLIED bit is used, Uniscribe
+       * seems to only care about the "last" transformation between
+       * Ligature and Multiple substitutions.  Ie. if you ligate, expand,
+       * and ligate again, it forgives the multiplication and acts as
+       * if only ligation happened.  As such, clear MULTIPLIED bit.
+       */
+      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    }
+    if (component)
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    if (likely (has_glyph_classes))
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
+    else if (class_guess)
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
+  }
+
+  void replace_glyph (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->replace_glyph (glyph_index);
+  }
+  void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->cur().codepoint = glyph_index;
+  }
+  void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
+                                          unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, true);
+    buffer->replace_glyph (glyph_index);
+  }
+  void output_glyph_for_component (hb_codepoint_t glyph_index,
+                                         unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, false, true);
+    buffer->output_glyph (glyph_index);
+  }
+};
+
+
+struct hb_get_subtables_context_t :
+       hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
+{
+  template <typename Type>
+  static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+  {
+    const Type *typed_obj = (const Type *) obj;
+    return typed_obj->apply (c);
+  }
+
+  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+
+  struct hb_applicable_t
+  {
+    template <typename T>
+    void init (const T &obj_, hb_apply_func_t apply_func_)
+    {
+      obj = &obj_;
+      apply_func = apply_func_;
+      digest.init ();
+      obj_.get_coverage ().add_coverage (&digest);
+    }
+
+    bool apply (OT::hb_ot_apply_context_t *c) const
+    {
+      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
+    }
+
+    private:
+    const void *obj;
+    hb_apply_func_t apply_func;
+    hb_set_digest_t digest;
+  };
+
+  typedef hb_vector_t<hb_applicable_t> array_t;
+
+  /* Dispatch interface. */
+  const char *get_name () { return "GET_SUBTABLES"; }
+  template <typename T>
+  return_t dispatch (const T &obj)
+  {
+    hb_applicable_t *entry = array.push();
+    entry->init (obj, apply_to<T>);
+    return HB_VOID;
+  }
+  static return_t default_return_value () { return HB_VOID; }
+
+  hb_get_subtables_context_t (array_t &array_) :
+                             array (array_),
+                             debug_depth (0) {}
+
+  array_t &array;
+  unsigned int debug_depth;
+};
+
+
+
+
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+struct ContextClosureFuncs
+{
+  intersects_func_t intersects;
+};
+struct ContextCollectGlyphsFuncs
+{
+  collect_glyphs_func_t collect;
+};
+struct ContextApplyFuncs
+{
+  match_func_t match;
+};
+
+
+static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyphs->has (value);
+}
+static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.intersects_class (glyphs, value);
+}
+static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).intersects (glyphs);
+}
+
+static inline bool intersects_array (const hb_set_t *glyphs,
+                                    unsigned int count,
+                                    const HBUINT16 values[],
+                                    intersects_func_t intersects_func,
+                                    const void *intersects_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    if (likely (!intersects_func (glyphs, values[i], intersects_data)))
+      return false;
+  return true;
+}
+
+
+static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  glyphs->add (value);
+}
+static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  class_def.add_class (glyphs, value);
+}
+static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  (data+coverage).add_coverage (glyphs);
+}
+static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
+                                 hb_set_t *glyphs,
+                                 unsigned int count,
+                                 const HBUINT16 values[],
+                                 collect_glyphs_func_t collect_func,
+                                 const void *collect_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    collect_func (glyphs, values[i], collect_data);
+}
+
+
+static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyph_id == value;
+}
+static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.get_class (glyph_id) == value;
+}
+static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+}
+
+static inline bool would_match_input (hb_would_apply_context_t *c,
+                                     unsigned int count, /* Including the first glyph (not matched) */
+                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                     match_func_t match_func,
+                                     const void *match_data)
+{
+  if (count != c->len)
+    return false;
+
+  for (unsigned int i = 1; i < count; i++)
+    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+      return false;
+
+  return true;
+}
+static inline bool match_input (hb_ot_apply_context_t *c,
+                               unsigned int count, /* Including the first glyph (not matched) */
+                               const HBUINT16 input[], /* Array of input values--start with second glyph */
+                               match_func_t match_func,
+                               const void *match_data,
+                               unsigned int *end_offset,
+                               unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+                               unsigned int *p_total_component_count = nullptr)
+{
+  TRACE_APPLY (nullptr);
+
+  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+  skippy_iter.reset (buffer->idx, count - 1);
+  skippy_iter.set_match_func (match_func, match_data, input);
+
+  /*
+   * This is perhaps the trickiest part of OpenType...  Remarks:
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *
+   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
+   *   it as a ligature glyph.
+   *
+   * - Ligatures cannot be formed across glyphs attached to different components
+   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
+   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
+   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
+   *   There are a couple of exceptions to this:
+   *
+   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
+   *     assuming that the font designer knows what they are doing (otherwise it can
+   *     break Indic stuff when a matra wants to ligate with a conjunct,
+   *
+   *   o If two marks want to ligate and they belong to different components of the
+   *     same ligature glyph, and said ligature glyph is to be ignored according to
+   *     mark-filtering rules, then allow.
+   *     https://github.com/harfbuzz/harfbuzz/issues/545
+   */
+
+  unsigned int total_component_count = 0;
+  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+
+  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+
+  enum {
+    LIGBASE_NOT_CHECKED,
+    LIGBASE_MAY_NOT_SKIP,
+    LIGBASE_MAY_SKIP
+  } ligbase = LIGBASE_NOT_CHECKED;
+
+  match_positions[0] = buffer->idx;
+  for (unsigned int i = 1; i < count; i++)
+  {
+    if (!skippy_iter.next ()) return_trace (false);
+
+    match_positions[i] = skippy_iter.idx;
+
+    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
+    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
+
+    if (first_lig_id && first_lig_comp)
+    {
+      /* If first component was attached to a previous ligature component,
+       * all subsequent components should be attached to the same ligature
+       * component, otherwise we shouldn't ligate them... */
+      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
+      {
+       /* ...unless, we are attached to a base ligature and that base
+        * ligature is ignorable. */
+       if (ligbase == LIGBASE_NOT_CHECKED)
+       {
+         bool found = false;
+         const hb_glyph_info_t *out = buffer->out_info;
+         unsigned int j = buffer->out_len;
+         while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
+         {
+           if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
+           {
+             j--;
+             found = true;
+             break;
+           }
+           j--;
+         }
+
+         if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
+           ligbase = LIGBASE_MAY_SKIP;
+         else
+           ligbase = LIGBASE_MAY_NOT_SKIP;
+       }
+
+       if (ligbase == LIGBASE_MAY_NOT_SKIP)
+         return_trace (false);
+      }
+    }
+    else
+    {
+      /* If first component was NOT attached to a previous ligature component,
+       * all subsequent components should also NOT be attached to any ligature
+       * component, unless they are attached to the first component itself! */
+      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
+       return_trace (false);
+    }
+
+    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
+  }
+
+  *end_offset = skippy_iter.idx - buffer->idx + 1;
+
+  if (p_total_component_count)
+    *p_total_component_count = total_component_count;
+
+  return_trace (true);
+}
+static inline bool ligate_input (hb_ot_apply_context_t *c,
+                                unsigned int count, /* Including the first glyph */
+                                const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                unsigned int match_length,
+                                hb_codepoint_t lig_glyph,
+                                unsigned int total_component_count)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
+
+  /* - If a base and one or more marks ligate, consider that as a base, NOT
+   *   ligature, such that all following marks can still attach to it.
+   *   https://github.com/harfbuzz/harfbuzz/issues/1109
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
+   *   the ligature to keep its old ligature id.  This will allow it to attach to
+   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
+   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
+   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
+   *   later, we don't want them to lose their ligature id/component, otherwise
+   *   GPOS will fail to correctly position the mark ligature on top of the
+   *   LAM,LAM,HEH ligature.  See:
+   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
+   *
+   * - If a ligature is formed of components that some of which are also ligatures
+   *   themselves, and those ligature components had marks attached to *their*
+   *   components, we have to attach the marks to the new ligature component
+   *   positions!  Now *that*'s tricky!  And these marks may be following the
+   *   last component of the whole sequence, so we should loop forward looking
+   *   for them and update them.
+   *
+   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
+   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
+   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
+   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
+   *   the new ligature with a component value of 2.
+   *
+   *   This in fact happened to a font...  See:
+   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
+   */
+
+  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[match_positions[0]]);
+  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[match_positions[0]]);
+  for (unsigned int i = 1; i < count; i++)
+    if (!_hb_glyph_info_is_mark (&buffer->info[match_positions[i]]))
+    {
+      is_base_ligature = false;
+      is_mark_ligature = false;
+      break;
+    }
+  bool is_ligature = !is_base_ligature && !is_mark_ligature;
+
+  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
+  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
+  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+  unsigned int components_so_far = last_num_components;
+
+  if (is_ligature)
+  {
+    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
+    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+    {
+      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
+    }
+  }
+  c->replace_glyph_with_ligature (lig_glyph, klass);
+
+  for (unsigned int i = 1; i < count; i++)
+  {
+    while (buffer->idx < match_positions[i] && buffer->successful)
+    {
+      if (is_ligature)
+      {
+       unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+       if (this_comp == 0)
+         this_comp = last_num_components;
+       unsigned int new_lig_comp = components_so_far - last_num_components +
+                                   MIN (this_comp, last_num_components);
+         _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
+      }
+      buffer->next_glyph ();
+    }
+
+    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+    components_so_far += last_num_components;
+
+    /* Skip the base glyph */
+    buffer->idx++;
+  }
+
+  if (!is_mark_ligature && last_lig_id) {
+    /* Re-adjust components for any marks following. */
+    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
+      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
+       unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+       if (!this_comp)
+         break;
+       unsigned int new_lig_comp = components_so_far - last_num_components +
+                                   MIN (this_comp, last_num_components);
+       _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
+      } else
+       break;
+    }
+  }
+  return_trace (true);
+}
+
+static inline bool match_backtrack (hb_ot_apply_context_t *c,
+                                   unsigned int count,
+                                   const HBUINT16 backtrack[],
+                                   match_func_t match_func,
+                                   const void *match_data,
+                                   unsigned int *match_start)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->backtrack_len (), count);
+  skippy_iter.set_match_func (match_func, match_data, backtrack);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.prev ())
+      return_trace (false);
+
+  *match_start = skippy_iter.idx;
+
+  return_trace (true);
+}
+
+static inline bool match_lookahead (hb_ot_apply_context_t *c,
+                                   unsigned int count,
+                                   const HBUINT16 lookahead[],
+                                   match_func_t match_func,
+                                   const void *match_data,
+                                   unsigned int offset,
+                                   unsigned int *end_index)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->idx + offset - 1, count);
+  skippy_iter.set_match_func (match_func, match_data, lookahead);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.next ())
+      return_trace (false);
+
+  *end_index = skippy_iter.idx + 1;
+
+  return_trace (true);
+}
+
+
+
+struct LookupRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16     sequenceIndex;          /* Index into current glyph
+                                        * sequence--first glyph = 0 */
+  HBUINT16     lookupListIndex;        /* Lookup to apply to that
+                                        * position--zero--based */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename context_t>
+static inline void recurse_lookups (context_t *c,
+                                   unsigned int lookupCount,
+                                   const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
+{
+  for (unsigned int i = 0; i < lookupCount; i++)
+    c->recurse (lookupRecord[i].lookupListIndex);
+}
+
+static inline bool apply_lookup (hb_ot_apply_context_t *c,
+                                unsigned int count, /* Including the first glyph */
+                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                unsigned int lookupCount,
+                                const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
+                                unsigned int match_length)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+  int end;
+
+  /* All positions are distance from beginning of *output* buffer.
+   * Adjust. */
+  {
+    unsigned int bl = buffer->backtrack_len ();
+    end = bl + match_length;
+
+    int delta = bl - buffer->idx;
+    /* Convert positions to new indexing. */
+    for (unsigned int j = 0; j < count; j++)
+      match_positions[j] += delta;
+  }
+
+  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
+  {
+    unsigned int idx = lookupRecord[i].sequenceIndex;
+    if (idx >= count)
+      continue;
+
+    /* Don't recurse to ourself at same position.
+     * Note that this test is too naive, it doesn't catch longer loops. */
+    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
+      continue;
+
+    if (unlikely (!buffer->move_to (match_positions[idx])))
+      break;
+
+    if (unlikely (buffer->max_ops <= 0))
+      break;
+
+    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    if (!c->recurse (lookupRecord[i].lookupListIndex))
+      continue;
+
+    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    int delta = new_len - orig_len;
+
+    if (!delta)
+      continue;
+
+    /* Recursed lookup changed buffer len.  Adjust.
+     *
+     * TODO:
+     *
+     * Right now, if buffer length increased by n, we assume n new glyphs
+     * were added right after the current position, and if buffer length
+     * was decreased by n, we assume n match positions after the current
+     * one where removed.  The former (buffer length increased) case is
+     * fine, but the decrease case can be improved in at least two ways,
+     * both of which are significant:
+     *
+     *   - If recursed-to lookup is MultipleSubst and buffer length
+     *     decreased, then it's current match position that was deleted,
+     *     NOT the one after it.
+     *
+     *   - If buffer length was decreased by n, it does not necessarily
+     *     mean that n match positions where removed, as there might
+     *     have been marks and default-ignorables in the sequence.  We
+     *     should instead drop match positions between current-position
+     *     and current-position + n instead.
+     *
+     * It should be possible to construct tests for both of these cases.
+     */
+
+    end += delta;
+    if (end <= int (match_positions[idx]))
+    {
+      /* End might end up being smaller than match_positions[idx] if the recursed
+       * lookup ended up removing many items, more than we have had matched.
+       * Just never rewind end back and get out of here.
+       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+      end = match_positions[idx];
+      /* There can't be any further changes. */
+      break;
+    }
+
+    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
+
+    if (delta > 0)
+    {
+      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
+       break;
+    }
+    else
+    {
+      /* NOTE: delta is negative. */
+      delta = MAX (delta, (int) next - (int) count);
+      next -= delta;
+    }
+
+    /* Shift! */
+    memmove (match_positions + next + delta, match_positions + next,
+            (count - next) * sizeof (match_positions[0]));
+    next += delta;
+    count += delta;
+
+    /* Fill in new entries. */
+    for (unsigned int j = idx + 1; j < next; j++)
+      match_positions[j] = match_positions[j - 1] + 1;
+
+    /* And fixup the rest. */
+    for (; next < count; next++)
+      match_positions[next] += delta;
+  }
+
+  buffer->move_to (end);
+
+  return_trace (true);
+}
+
+
+
+/* Contextual lookups */
+
+struct ContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data;
+};
+
+struct ContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data;
+};
+
+struct ContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data;
+};
+
+static inline bool context_intersects (const hb_set_t *glyphs,
+                                      unsigned int inputCount, /* Including the first glyph (not matched) */
+                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                      ContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                          inputCount ? inputCount - 1 : 0, input,
+                          lookup_context.funcs.intersects, lookup_context.intersects_data);
+}
+
+static inline void context_closure_lookup (hb_closure_context_t *c,
+                                          unsigned int inputCount, /* Including the first glyph (not matched) */
+                                          const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                          unsigned int lookupCount,
+                                          const LookupRecord lookupRecord[],
+                                          ContextClosureLookupContext &lookup_context)
+{
+  if (context_intersects (c->glyphs,
+                         inputCount, input,
+                         lookup_context))
+    recurse_lookups (c,
+                    lookupCount, lookupRecord);
+}
+
+static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                 unsigned int lookupCount,
+                                                 const LookupRecord lookupRecord[],
+                                                 ContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->input,
+                inputCount ? inputCount - 1 : 0, input,
+                lookup_context.funcs.collect, lookup_context.collect_data);
+  recurse_lookups (c,
+                  lookupCount, lookupRecord);
+}
+
+static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
+                                              unsigned int inputCount, /* Including the first glyph (not matched) */
+                                              const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                              unsigned int lookupCount HB_UNUSED,
+                                              const LookupRecord lookupRecord[] HB_UNUSED,
+                                              ContextApplyLookupContext &lookup_context)
+{
+  return would_match_input (c,
+                           inputCount, input,
+                           lookup_context.funcs.match, lookup_context.match_data);
+}
+static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
+                                        unsigned int inputCount, /* Including the first glyph (not matched) */
+                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                        unsigned int lookupCount,
+                                        const LookupRecord lookupRecord[],
+                                        ContextApplyLookupContext &lookup_context)
+{
+  unsigned int match_length = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                     inputCount, input,
+                     lookup_context.funcs.match, lookup_context.match_data,
+                     &match_length, match_positions)
+      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
+         apply_lookup (c,
+                      inputCount, match_positions,
+                      lookupCount, lookupRecord,
+                      match_length));
+}
+
+struct Rule
+{
+  bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
+  {
+    return context_intersects (glyphs,
+                              inputCount, inputZ.arrayZ,
+                              lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                      (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+    context_closure_lookup (c,
+                           inputCount, inputZ.arrayZ,
+                           lookupCount, lookupRecord.arrayZ,
+                           lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                      ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                      (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    context_collect_glyphs_lookup (c,
+                                  inputCount, inputZ.arrayZ,
+                                  lookupCount, lookupRecord.arrayZ,
+                                  lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                   ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                      (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+             ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                      (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (inputCount.sanitize (c) &&
+                 lookupCount.sanitize (c) &&
+                 c->check_range (inputZ.arrayZ,
+                                 inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
+                                 LookupRecord::static_size * lookupCount));
+  }
+
+  protected:
+  HBUINT16     inputCount;             /* Total number of glyphs in input
+                                        * glyph sequence--includes the first
+                                        * glyph */
+  HBUINT16     lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<HBUINT16>
+               inputZ;                 /* Array of match inputs--start with
+                                        * second glyph */
+/*UnsizedArrayOf<LookupRecord>
+               lookupRecordX;*/        /* Array of LookupRecords--in
+                                        * design order */
+  public:
+  DEFINE_SIZE_ARRAY (4, inputZ);
+};
+
+struct RuleSet
+{
+  bool intersects (const hb_set_t *glyphs,
+                  ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+       return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c,
+               ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                      ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                   ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).would_apply (c, lookup_context))
+       return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+             ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).apply (c, lookup_context))
+       return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<Rule>
+               rule;                   /* Array of Rule tables
+                                        * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+
+struct ContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+         (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+       return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+       (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED))
+      return_trace (false);
+
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+               coverage;               /* Offset to Coverage table--from
+                                        * beginning of table */
+  OffsetArrayOf<RuleSet>
+               ruleSet;                /* Array of RuleSet tables
+                                        * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+
+struct ContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (glyphs, i) &&
+         (this+ruleSet[i]).intersects (glyphs, lookup_context))
+       return true;
+
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (c->glyphs, i)) {
+       const RuleSet &rule_set = this+ruleSet[i];
+       rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &class_def = this+classDef;
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &class_def = this+classDef;
+    unsigned int index = class_def.get_class (c->glyphs[0]);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &class_def = this+classDef;
+    index = class_def.get_class (c->buffer->cur().codepoint);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+               coverage;               /* Offset to Coverage table--from
+                                        * beginning of table */
+  OffsetTo<ClassDef>
+               classDef;               /* Offset to glyph ClassDef table--from
+                                        * beginning of table */
+  OffsetArrayOf<RuleSet>
+               ruleSet;                /* Array of RuleSet tables
+                                        * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (8, ruleSet);
+};
+
+
+struct ContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverageZ[0]).intersects (glyphs))
+      return false;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    return context_intersects (glyphs,
+                              glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                              lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverageZ[0]).intersects (c->glyphs))
+      return;
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    context_closure_lookup (c,
+                           glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                           lookupCount, lookupRecord,
+                           lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverageZ[0]).add_coverage (c->input);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      this
+    };
+
+    context_collect_glyphs_lookup (c,
+                                  glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                                  lookupCount, lookupRecord,
+                                  lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverageZ[0]; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!c->check_struct (this)) return_trace (false);
+    unsigned int count = glyphCount;
+    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    return_trace (c->check_array (lookupRecord, lookupCount));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 3 */
+  HBUINT16     glyphCount;             /* Number of glyphs in the input glyph
+                                        * sequence */
+  HBUINT16     lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<OffsetTo<Coverage> >
+               coverageZ;              /* Array of offsets to Coverage
+                                        * table in glyph sequence order */
+/*UnsizedArrayOf<LookupRecord>
+               lookupRecordX;*/        /* Array of LookupRecords--in
+                                        * design order */
+  public:
+  DEFINE_SIZE_ARRAY (6, coverageZ);
+};
+
+struct Context
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  ContextFormat1       format1;
+  ContextFormat2       format2;
+  ContextFormat3       format3;
+  } u;
+};
+
+
+/* Chaining Contextual lookups */
+
+struct ChainContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data[3];
+};
+
+struct ChainContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data[3];
+};
+
+struct ChainContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data[3];
+};
+
+static inline bool chain_context_intersects (const hb_set_t *glyphs,
+                                            unsigned int backtrackCount,
+                                            const HBUINT16 backtrack[],
+                                            unsigned int inputCount, /* Including the first glyph (not matched) */
+                                            const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                            unsigned int lookaheadCount,
+                                            const HBUINT16 lookahead[],
+                                            ChainContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                          backtrackCount, backtrack,
+                          lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+      && intersects_array (glyphs,
+                          inputCount ? inputCount - 1 : 0, input,
+                          lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+      && intersects_array (glyphs,
+                         lookaheadCount, lookahead,
+                         lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+}
+
+static inline void chain_context_closure_lookup (hb_closure_context_t *c,
+                                                unsigned int backtrackCount,
+                                                const HBUINT16 backtrack[],
+                                                unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                unsigned int lookaheadCount,
+                                                const HBUINT16 lookahead[],
+                                                unsigned int lookupCount,
+                                                const LookupRecord lookupRecord[],
+                                                ChainContextClosureLookupContext &lookup_context)
+{
+  if (chain_context_intersects (c->glyphs,
+                               backtrackCount, backtrack,
+                               inputCount, input,
+                               lookaheadCount, lookahead,
+                               lookup_context))
+    recurse_lookups (c,
+                    lookupCount, lookupRecord);
+}
+
+static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                       unsigned int backtrackCount,
+                                                       const HBUINT16 backtrack[],
+                                                       unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                       unsigned int lookaheadCount,
+                                                       const HBUINT16 lookahead[],
+                                                       unsigned int lookupCount,
+                                                       const LookupRecord lookupRecord[],
+                                                       ChainContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->before,
+                backtrackCount, backtrack,
+                lookup_context.funcs.collect, lookup_context.collect_data[0]);
+  collect_array (c, c->input,
+                inputCount ? inputCount - 1 : 0, input,
+                lookup_context.funcs.collect, lookup_context.collect_data[1]);
+  collect_array (c, c->after,
+                lookaheadCount, lookahead,
+                lookup_context.funcs.collect, lookup_context.collect_data[2]);
+  recurse_lookups (c,
+                  lookupCount, lookupRecord);
+}
+
+static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
+                                                    unsigned int backtrackCount,
+                                                    const HBUINT16 backtrack[] HB_UNUSED,
+                                                    unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                    const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                    unsigned int lookaheadCount,
+                                                    const HBUINT16 lookahead[] HB_UNUSED,
+                                                    unsigned int lookupCount HB_UNUSED,
+                                                    const LookupRecord lookupRecord[] HB_UNUSED,
+                                                    ChainContextApplyLookupContext &lookup_context)
+{
+  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
+      && would_match_input (c,
+                           inputCount, input,
+                           lookup_context.funcs.match, lookup_context.match_data[1]);
+}
+
+static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                                              unsigned int backtrackCount,
+                                              const HBUINT16 backtrack[],
+                                              unsigned int inputCount, /* Including the first glyph (not matched) */
+                                              const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                              unsigned int lookaheadCount,
+                                              const HBUINT16 lookahead[],
+                                              unsigned int lookupCount,
+                                              const LookupRecord lookupRecord[],
+                                              ChainContextApplyLookupContext &lookup_context)
+{
+  unsigned int start_index = 0, match_length = 0, end_index = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                     inputCount, input,
+                     lookup_context.funcs.match, lookup_context.match_data[1],
+                     &match_length, match_positions)
+      && match_backtrack (c,
+                         backtrackCount, backtrack,
+                         lookup_context.funcs.match, lookup_context.match_data[0],
+                         &start_index)
+      && match_lookahead (c,
+                         lookaheadCount, lookahead,
+                         lookup_context.funcs.match, lookup_context.match_data[2],
+                         match_length, &end_index)
+      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
+         apply_lookup (c,
+                       inputCount, match_positions,
+                       lookupCount, lookupRecord,
+                       match_length));
+}
+
+struct ChainRule
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    return chain_context_intersects (glyphs,
+                                    backtrack.len, backtrack.arrayZ,
+                                    input.lenP1, input.arrayZ,
+                                    lookahead.len, lookahead.arrayZ,
+                                    lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c,
+               ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_closure_lookup (c,
+                                 backtrack.len, backtrack.arrayZ,
+                                 input.lenP1, input.arrayZ,
+                                 lookahead.len, lookahead.arrayZ,
+                                 lookup.len, lookup.arrayZ,
+                                 lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                      ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_collect_glyphs_lookup (c,
+                                        backtrack.len, backtrack.arrayZ,
+                                        input.lenP1, input.arrayZ,
+                                        lookahead.len, lookahead.arrayZ,
+                                        lookup.len, lookup.arrayZ,
+                                        lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                   ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_would_apply_lookup (c,
+                                                   backtrack.len, backtrack.arrayZ,
+                                                   input.lenP1, input.arrayZ,
+                                                   lookahead.len, lookahead.arrayZ, lookup.len,
+                                                   lookup.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_apply_lookup (c,
+                                             backtrack.len, backtrack.arrayZ,
+                                             input.lenP1, input.arrayZ,
+                                             lookahead.len, lookahead.arrayZ, lookup.len,
+                                             lookup.arrayZ, lookup_context));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c)) return_trace (false);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    if (!input.sanitize (c)) return_trace (false);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    if (!lookahead.sanitize (c)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<HBUINT16>
+               backtrack;              /* Array of backtracking values
+                                        * (to be matched before the input
+                                        * sequence) */
+  HeadlessArrayOf<HBUINT16>
+               inputX;                 /* Array of input values (start with
+                                        * second glyph) */
+  ArrayOf<HBUINT16>
+               lookaheadX;             /* Array of lookahead values's (to be
+                                        * matched after the input sequence) */
+  ArrayOf<LookupRecord>
+               lookupX;                /* Array of LookupRecords--in
+                                        * design order) */
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct ChainRuleSet
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+       return true;
+    return false;
+  }
+  void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).would_apply (c, lookup_context))
+       return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).apply (c, lookup_context))
+       return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<ChainRule>
+               rule;                   /* Array of ChainRule tables
+                                        * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+struct ChainContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+         (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+       return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+       break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+       (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+               coverage;               /* Offset to Coverage table--from
+                                        * beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+               ruleSet;                /* Array of ChainRuleSet tables
+                                        * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+struct ChainContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (glyphs, i) &&
+         (this+ruleSet[i]).intersects (glyphs, lookup_context))
+       return true;
+
+    return false;
+  }
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (c->glyphs, i)) {
+       const ChainRuleSet &rule_set = this+ruleSet[i];
+       rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    unsigned int index = input_class_def.get_class (c->glyphs[0]);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    index = input_class_def.get_class (c->buffer->cur().codepoint);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) &&
+                 backtrackClassDef.sanitize (c, this) &&
+                 inputClassDef.sanitize (c, this) &&
+                 lookaheadClassDef.sanitize (c, this) &&
+                 ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+               coverage;               /* Offset to Coverage table--from
+                                        * beginning of table */
+  OffsetTo<ClassDef>
+               backtrackClassDef;      /* Offset to glyph ClassDef table
+                                        * containing backtrack sequence
+                                        * data--from beginning of table */
+  OffsetTo<ClassDef>
+               inputClassDef;          /* Offset to glyph ClassDef
+                                        * table containing input sequence
+                                        * data--from beginning of table */
+  OffsetTo<ClassDef>
+               lookaheadClassDef;      /* Offset to glyph ClassDef table
+                                        * containing lookahead sequence
+                                        * data--from beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+               ruleSet;                /* Array of ChainRuleSet tables
+                                        * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (12, ruleSet);
+};
+
+struct ChainContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    return chain_context_intersects (glyphs,
+                                    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                    input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                    lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (c->glyphs))
+      return;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    chain_context_closure_lookup (c,
+                                 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                 input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                 lookup.len, lookup.arrayZ,
+                                 lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    (this+input[0]).add_coverage (c->input);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      {this, this, this}
+    };
+    chain_context_collect_glyphs_lookup (c,
+                                        backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                        input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                        lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                        lookup.len, lookup.arrayZ,
+                                        lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_would_apply_lookup (c,
+                                                   backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                                   input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                                   lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                                   lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  const Coverage &get_coverage () const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    return this+input[0];
+  }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_apply_lookup (c,
+                                             backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                             input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                             lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                             lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c, this)) return_trace (false);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    if (!input.sanitize (c, this)) return_trace (false);
+    if (!input.len) return_trace (false); /* To be consistent with Context. */
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    if (!lookahead.sanitize (c, this)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier--format = 3 */
+  OffsetArrayOf<Coverage>
+               backtrack;              /* Array of coverage tables
+                                        * in backtracking sequence, in  glyph
+                                        * sequence order */
+  OffsetArrayOf<Coverage>
+               inputX          ;       /* Array of coverage
+                                        * tables in input sequence, in glyph
+                                        * sequence order */
+  OffsetArrayOf<Coverage>
+               lookaheadX;             /* Array of coverage tables
+                                        * in lookahead sequence, in glyph
+                                        * sequence order */
+  ArrayOf<LookupRecord>
+               lookupX;                /* Array of LookupRecords--in
+                                        * design order) */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+struct ChainContext
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format; /* Format identifier */
+  ChainContextFormat1  format1;
+  ChainContextFormat2  format2;
+  ChainContextFormat3  format3;
+  } u;
+};
+
+
+template <typename T>
+struct ExtensionFormat1
+{
+  unsigned int get_type () const { return extensionLookupType; }
+
+  template <typename X>
+  const X& get_subtable () const
+  {
+    unsigned int offset = extensionOffset;
+    if (unlikely (!offset)) return Null(typename T::SubTable);
+    return StructAtOffset<typename T::SubTable> (this, offset);
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, format);
+    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
+    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
+  }
+
+  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                 extensionOffset != 0 &&
+                 extensionLookupType != T::SubTable::Extension);
+  }
+
+  protected:
+  HBUINT16     format;                 /* Format identifier. Set to 1. */
+  HBUINT16     extensionLookupType;    /* Lookup type of subtable referenced
+                                        * by ExtensionOffset (i.e. the
+                                        * extension subtable). */
+  HBUINT32     extensionOffset;        /* Offset to the extension subtable,
+                                        * of lookup type subtable. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename T>
+struct Extension
+{
+  unsigned int get_type () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_type ();
+    default:return 0;
+    }
+  }
+  template <typename X>
+  const X& get_subtable () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.template get_subtable<typename T::SubTable> ();
+    default:return Null(typename T::SubTable);
+    }
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (u.format1.dispatch (c));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16             format;         /* Format identifier */
+  ExtensionFormat1<T>  format1;
+  } u;
+};
+
+
+/*
+ * GSUB/GPOS Common
+ */
+
+struct hb_ot_layout_lookup_accelerator_t
+{
+  template <typename TLookup>
+  void init (const TLookup &lookup)
+  {
+    digest.init ();
+    lookup.add_coverage (&digest);
+
+    subtables.init ();
+    OT::hb_get_subtables_context_t c_get_subtables (subtables);
+    lookup.dispatch (&c_get_subtables);
+  }
+  void fini () { subtables.fini (); }
+
+  bool may_have (hb_codepoint_t g) const
+  { return digest.may_have (g); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    for (unsigned int i = 0; i < subtables.length; i++)
+      if (subtables[i].apply (c))
+       return true;
+    return false;
+  }
+
+  private:
+  hb_set_digest_t digest;
+  hb_get_subtables_context_t::array_t subtables;
+};
+
+struct GSUBGPOS
+{
+  bool has_data () const { return version.to_int (); }
+  unsigned int get_script_count () const
+  { return (this+scriptList).len; }
+  const Tag& get_script_tag (unsigned int i) const
+  { return (this+scriptList).get_tag (i); }
+  unsigned int get_script_tags (unsigned int start_offset,
+                               unsigned int *script_count /* IN/OUT */,
+                               hb_tag_t     *script_tags /* OUT */) const
+  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+  const Script& get_script (unsigned int i) const
+  { return (this+scriptList)[i]; }
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+scriptList).find_index (tag, index); }
+
+  unsigned int get_feature_count () const
+  { return (this+featureList).len; }
+  hb_tag_t get_feature_tag (unsigned int i) const
+  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+  unsigned int get_feature_tags (unsigned int start_offset,
+                                unsigned int *feature_count /* IN/OUT */,
+                                hb_tag_t     *feature_tags /* OUT */) const
+  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+  const Feature& get_feature (unsigned int i) const
+  { return (this+featureList)[i]; }
+  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+featureList).find_index (tag, index); }
+
+  unsigned int get_lookup_count () const
+  { return (this+lookupList).len; }
+  const Lookup& get_lookup (unsigned int i) const
+  { return (this+lookupList)[i]; }
+
+  bool find_variations_index (const int *coords, unsigned int num_coords,
+                             unsigned int *index) const
+  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+          .find_index (coords, num_coords, index); }
+  const Feature& get_feature_variation (unsigned int feature_index,
+                                       unsigned int variations_index) const
+  {
+    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
+       version.to_int () >= 0x00010001u)
+    {
+      const Feature *feature = (this+featureVars).find_substitute (variations_index,
+                                                                  feature_index);
+      if (feature)
+       return *feature;
+    }
+    return get_feature (feature_index);
+  }
+
+  template <typename TLookup>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GSUBGPOS *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->scriptList.serialize_subset (c, this+scriptList, out);
+    out->featureList.serialize_subset (c, this+featureList, out);
+
+    typedef OffsetListOf<TLookup> TLookupList;
+    /* TODO Use intersects() to count how many subtables survive? */
+    CastR<OffsetTo<TLookupList> > (out->lookupList)
+      .serialize_subset (c,
+                        this+CastR<const OffsetTo<TLookupList> > (lookupList),
+                        out);
+
+    if (version.to_int () >= 0x00010001u)
+     out->featureVars.serialize_subset (c, this+featureVars, out);
+
+    return_trace (true);
+  }
+
+  unsigned int get_size () const
+  {
+    return min_size +
+          (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+  }
+
+  template <typename TLookup>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    typedef OffsetListOf<TLookup> TLookupList;
+    return_trace (version.sanitize (c) &&
+                 likely (version.major == 1) &&
+                 scriptList.sanitize (c, this) &&
+                 featureList.sanitize (c, this) &&
+                 CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
+                 (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
+  }
+
+  template <typename T>
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<T> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+       hb_blob_destroy (this->table.get_blob ());
+       this->table = hb_blob_get_empty ();
+      }
+
+      this->lookup_count = table->get_lookup_count ();
+
+      this->accels = (hb_ot_layout_lookup_accelerator_t *) calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
+      if (unlikely (!this->accels))
+       this->lookup_count = 0;
+
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+       this->accels[i].init (table->get_lookup (i));
+    }
+
+    void fini ()
+    {
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+       this->accels[i].fini ();
+      free (this->accels);
+      this->table.destroy ();
+    }
+
+    hb_blob_ptr_t<T> table;
+    unsigned int lookup_count;
+    hb_ot_layout_lookup_accelerator_t *accels;
+  };
+
+  protected:
+  FixedVersion<>version;       /* Version of the GSUB/GPOS table--initially set
+                                * to 0x00010000u */
+  OffsetTo<ScriptList>
+               scriptList;     /* ScriptList table */
+  OffsetTo<FeatureList>
+               featureList;    /* FeatureList table */
+  OffsetTo<LookupList>
+               lookupList;     /* LookupList table */
+  LOffsetTo<FeatureVariations>
+               featureVars;    /* Offset to Feature Variations
+                                  table--from beginning of table
+                                * (may be NULL).  Introduced
+                                * in version 0x00010001. */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */
index 7fabdeb..1dd31d5 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_LAYOUT_JSTF_TABLE_HH
 #define HB_OT_LAYOUT_JSTF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-layout-gpos-table.hh"
 
 
@@ -54,7 +54,7 @@ typedef OffsetListOf<PosLookup> JstfMax;
 
 struct JstfPriority
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -123,8 +123,8 @@ struct JstfPriority
 
 struct JstfLangSys : OffsetListOf<JstfPriority>
 {
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (OffsetListOf<JstfPriority>::sanitize (c));
@@ -145,27 +145,27 @@ typedef SortedArrayOf<GlyphID> ExtenderGlyphs;
 
 struct JstfScript
 {
-  inline unsigned int get_lang_sys_count (void) const
+  unsigned int get_lang_sys_count () const
   { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
+  const Tag& get_lang_sys_tag (unsigned int i) const
   { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                        unsigned int *lang_sys_count /* IN/OUT */,
-                                        hb_tag_t     *lang_sys_tags /* OUT */) const
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                 unsigned int *lang_sys_count /* IN/OUT */,
+                                 hb_tag_t     *lang_sys_tags /* OUT */) const
   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const JstfLangSys& get_lang_sys (unsigned int i) const
+  const JstfLangSys& get_lang_sys (unsigned int i) const
   {
     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
     return this+langSys[i].offset;
   }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   { return langSys.find_index (tag, index); }
 
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
+  bool has_default_lang_sys () const               { return defaultLangSys != 0; }
+  const JstfLangSys& get_default_lang_sys () const { return this+defaultLangSys; }
 
-  inline bool sanitize (hb_sanitize_context_t *c,
-                       const Record<JstfScript>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (extenderGlyphs.sanitize (c, this) &&
@@ -195,22 +195,22 @@ struct JstfScript
 
 struct JSTF
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_JSTF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_JSTF;
 
-  inline unsigned int get_script_count (void) const
+  unsigned int get_script_count () const
   { return scriptList.len; }
-  inline const Tag& get_script_tag (unsigned int i) const
+  const Tag& get_script_tag (unsigned int i) const
   { return scriptList.get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                      unsigned int *script_count /* IN/OUT */,
-                                      hb_tag_t     *script_tags /* OUT */) const
+  unsigned int get_script_tags (unsigned int start_offset,
+                               unsigned int *script_count /* IN/OUT */,
+                               hb_tag_t     *script_tags /* OUT */) const
   { return scriptList.get_tags (start_offset, script_count, script_tags); }
-  inline const JstfScript& get_script (unsigned int i) const
+  const JstfScript& get_script (unsigned int i) const
   { return this+scriptList[i].offset; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return scriptList.find_index (tag, index); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
deleted file mode 100644 (file)
index b2f974b..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012,2013  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
- */
-
-#ifndef HB_OT_LAYOUT_PRIVATE_HH
-#define HB_OT_LAYOUT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-set-digest-private.hh"
-#include "hb-open-type-private.hh"
-
-
-/* Private API corresponding to hb-ot-layout.h: */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_table_find_feature (hb_face_t    *face,
-                                hb_tag_t      table_tag,
-                                hb_tag_t      feature_tag,
-                                unsigned int *feature_index);
-
-
-/*
- * GDEF
- */
-
-enum hb_ot_layout_glyph_props_flags_t
-{
-  /* The following three match LookupFlags::Ignore* numbers. */
-  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH  = 0x02u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE    = 0x04u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MARK                = 0x08u,
-
-  /* The following are used internally; not derived from GDEF. */
-  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED     = 0x20u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED  = 0x40u,
-
-  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-                                         HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                                         HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
-};
-HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
-
-
-/*
- * GSUB/GPOS
- */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
-                                          unsigned int          lookup_index,
-                                          const hb_codepoint_t *glyphs,
-                                          unsigned int          glyphs_length,
-                                          hb_bool_t             zero_context);
-
-
-/* Should be called before all the substitute_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_substitute_start (hb_font_t    *font,
-                              hb_buffer_t  *buffer);
-
-
-struct hb_ot_layout_lookup_accelerator_t;
-
-namespace OT {
-  struct hb_ot_apply_context_t;
-  struct SubstLookup;
-}
-
-HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
-                               const OT::SubstLookup &lookup,
-                               const hb_ot_layout_lookup_accelerator_t &accel);
-
-
-/* Should be called before all the position_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_position_start (hb_font_t    *font,
-                            hb_buffer_t  *buffer);
-
-/* Should be called after all the position_lookup's are done, to fini advances. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_advances (hb_font_t    *font,
-                                      hb_buffer_t  *buffer);
-
-/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_offsets (hb_font_t    *font,
-                                     hb_buffer_t  *buffer);
-
-
-
-/*
- * hb_ot_layout_t
- */
-
-namespace OT {
-  struct BASE;
-  struct COLR;
-  struct CPAL;
-  struct GDEF;
-  struct GSUB;
-  struct GPOS;
-  struct MATH;
-  struct fvar;
-  struct avar;
-}
-
-namespace AAT {
-  struct ankr;
-  struct kerx;
-  struct morx;
-  struct trak;
-}
-
-struct hb_ot_layout_lookup_accelerator_t
-{
-  template <typename TLookup>
-  inline void init (const TLookup &lookup)
-  {
-    digest.init ();
-    lookup.add_coverage (&digest);
-  }
-
-  inline void fini (void)
-  {
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return digest.may_have (g);
-  }
-
-  private:
-  hb_set_digest_t digest;
-};
-
-struct hb_ot_layout_t
-{
-  hb_blob_t *gdef_blob;
-  hb_blob_t *gsub_blob;
-  hb_blob_t *gpos_blob;
-
-  const struct OT::GDEF *gdef;
-  const struct OT::GSUB *gsub;
-  const struct OT::GPOS *gpos;
-
-  /* TODO Move the following out of this struct. */
-  OT::hb_table_lazy_loader_t<struct OT::BASE> base;
-  OT::hb_table_lazy_loader_t<struct OT::MATH> math;
-  OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
-  OT::hb_table_lazy_loader_t<struct OT::avar> avar;
-
-  unsigned int gsub_lookup_count;
-  unsigned int gpos_lookup_count;
-
-  hb_ot_layout_lookup_accelerator_t *gsub_accels;
-  hb_ot_layout_lookup_accelerator_t *gpos_accels;
-};
-
-
-HB_INTERNAL hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face);
-
-HB_INTERNAL void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-
-
-#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
-
-
-/*
- * Buffer var routines.
- */
-
-/* buffer var allocations, used during the entire shaping process */
-#define unicode_props()                var2.u16[0]
-
-/* buffer var allocations, used during the GSUB/GPOS processing */
-#define glyph_props()          var1.u16[0] /* GDEF glyph properties */
-#define lig_props()            var1.u8[2] /* GSUB/GPOS ligature tracking */
-#define syllable()             var1.u8[3] /* GSUB/GPOS shaping boundaries */
-
-
-/* Loop over syllables. Based on foreach_cluster(). */
-#define foreach_syllable(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_syllable (buffer, start))
-
-static inline unsigned int
-_next_syllable (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int syllable = info[start].syllable();
-  while (++start < count && syllable == info[start].syllable())
-    ;
-
-  return start;
-}
-
-
-/* unicode_props */
-
-/* Design:
- * unicode_props() is a two-byte number.  The low byte includes:
- * - General_Category: 5 bits.
- * - A bit each for:
- *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Whether it's one of the three Mongolian Free Variation Selectors,
- *     CGJ, or other characters that are hidden but should not be ignored
- *     like most other Default_Ignorable()s do during matching.
- *   * One free bit right now.
- *
- * The high-byte has different meanings, switched by the Gen-Cat:
- * - For Mn,Mc,Me: the modified Combining_Class.
- * - For Cf: whether it's ZWJ, ZWNJ, or something else.
- * - For Ws: index of which space character this is, if space fallback
- *   is needed, ie. we don't set this by default, only if asked to.
- */
-
-enum hb_unicode_props_flags_t {
-  UPROPS_MASK_GEN_CAT  = 0x001Fu,
-  UPROPS_MASK_IGNORABLE        = 0x0020u,
-  UPROPS_MASK_HIDDEN   = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
-                                    * or TAG characters */
-
-  /* If GEN_CAT=FORMAT, top byte masks: */
-  UPROPS_MASK_Cf_ZWJ   = 0x0100u,
-  UPROPS_MASK_Cf_ZWNJ  = 0x0200u
-};
-HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
-
-static inline void
-_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
-{
-  hb_unicode_funcs_t *unicode = buffer->unicode;
-  unsigned int u = info->codepoint;
-  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
-  unsigned int props = gen_cat;
-
-  if (u >= 0x80)
-  {
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
-    if (unlikely (unicode->is_default_ignorable (u)))
-    {
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
-      props |=  UPROPS_MASK_IGNORABLE;
-      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
-      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
-      /* Mongolian Free Variation Selectors need to be remembered
-       * because although we need to hide them like default-ignorables,
-       * they need to non-ignorable during shaping.  This is similar to
-       * what we do for joiners in Indic-like shapers, but since the
-       * FVSes are GC=Mn, we have use a separate bit to remember them.
-       * Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/234 */
-      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
-      /* TAG characters need similar treatment. Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/463 */
-      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
-       * https://github.com/harfbuzz/harfbuzz/issues/554 */
-      else if (unlikely (u == 0x034Fu))
-      {
-       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
-       props |= UPROPS_MASK_HIDDEN;
-      }
-    }
-    else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
-    {
-      /* The above check is just an optimization to let in only things we need further
-       * processing on. */
-
-      /* Only Mn and Mc can have non-zero ccc:
-       * https://unicode.org/policies/stability_policy.html#Property_Value
-       * """
-       * Canonical_Combining_Class, General_Category
-       * All characters other than those with General_Category property values
-       * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
-       * property value 0.
-       * 1.1.5+
-       * """
-       *
-       * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
-       * the "else if".
-       */
-      props |= unicode->modified_combining_class (info->codepoint)<<8;
-
-      /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
-       * behave correctly in non-native directionality.  They originally
-       * are MODIFIER_SYMBOL.  Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/169
-       */
-      if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
-      {
-       props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
-      }
-    }
-  }
-
-  info->unicode_props() = props;
-}
-
-static inline void
-_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
-                                    hb_unicode_general_category_t gen_cat)
-{
-  /* Clears top-byte. */
-  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
-}
-
-static inline hb_unicode_general_category_t
-_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
-{
-  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
-{
-  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-static inline void
-_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
-                                            unsigned int modified_class)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
-    return;
-  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
-}
-static inline unsigned int
-_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
-}
-
-
-/* Loop over grapheme. Based on foreach_cluster(). */
-#define foreach_grapheme(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_grapheme (buffer, start))
-
-static inline unsigned int
-_next_grapheme (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
-    ;
-
-  return start;
-}
-
-
-#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
-
-static inline bool
-_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-        HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
-}
-static inline void
-_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
-    return;
-  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
-}
-static inline hb_unicode_funcs_t::space_t
-_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_space (info) ?
-        (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
-        hb_unicode_funcs_t::NOT_SPACE;
-}
-
-static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
-
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
-{
-  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
-        !_hb_glyph_info_ligated (info);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
-{
-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
-         == UPROPS_MASK_IGNORABLE) &&
-        !_hb_glyph_info_ligated (info);
-}
-static inline void
-_hb_glyph_info_unhide (hb_glyph_info_t *info)
-{
-  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-        HB_UNICODE_GENERAL_CATEGORY_FORMAT;
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
-}
-static inline void
-_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
-{
-  if (!_hb_glyph_info_is_unicode_format (info))
-    return;
-  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
-}
-
-/* lig_props: aka lig_id / lig_comp
- *
- * When a ligature is formed:
- *
- *   - The ligature glyph and any marks in between all the same newly allocated
- *     lig_id,
- *   - The ligature glyph will get lig_num_comps set to the number of components
- *   - The marks get lig_comp > 0, reflecting which component of the ligature
- *     they were applied to.
- *   - This is used in GPOS to attach marks to the right component of a ligature
- *     in MarkLigPos,
- *   - Note that when marks are ligated together, much of the above is skipped
- *     and the current lig_id reused.
- *
- * When a multiple-substitution is done:
- *
- *   - All resulting glyphs will have lig_id = 0,
- *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
- *   - This is used in GPOS to attach marks to the first component of a
- *     multiple substitution in MarkBasePos.
- *
- * The numbers are also used in GPOS to do mark-to-mark positioning only
- * to marks that belong to the same component of the same ligature.
- */
-
-static inline void
-_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
-{
-  info->lig_props() = 0;
-}
-
-#define IS_LIG_BASE 0x10
-
-static inline void
-_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
-                                          unsigned int lig_id,
-                                          unsigned int lig_num_comps)
-{
-  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
-                                      unsigned int lig_id,
-                                      unsigned int lig_comp)
-{
-  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
-{
-  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
-{
-  return info->lig_props() >> 5;
-}
-
-static inline bool
-_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
-{
-  return !!(info->lig_props() & IS_LIG_BASE);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
-{
-  if (_hb_glyph_info_ligated_internal (info))
-    return 0;
-  else
-    return info->lig_props() & 0x0F;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
-{
-  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
-      _hb_glyph_info_ligated_internal (info))
-    return info->lig_props() & 0x0F;
-  else
-    return 1;
-}
-
-static inline uint8_t
-_hb_allocate_lig_id (hb_buffer_t *buffer) {
-  uint8_t lig_id = buffer->next_serial () & 0x07;
-  if (unlikely (!lig_id))
-    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
-  return lig_id;
-}
-
-/* glyph_props: */
-
-static inline void
-_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
-{
-  info->glyph_props() = props;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
-{
-  return info->glyph_props();
-}
-
-static inline bool
-_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
-}
-
-static inline bool
-_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
-}
-
-static inline bool
-_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
-}
-
-static inline bool
-_hb_glyph_info_substituted (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-static inline bool
-_hb_glyph_info_ligated (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
-}
-
-static inline bool
-_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline bool
-_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
-}
-
-static inline void
-_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline void
-_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-
-/* Allocation / deallocation. */
-
-static inline void
-_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
-}
-
-static inline void
-_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
-}
-
-static inline void
-_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
-  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
-  HB_BUFFER_ASSERT_VAR (buffer, syllable);
-}
-
-/* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
-#undef lig_props
-#undef glyph_props
-
-#endif /* HB_OT_LAYOUT_PRIVATE_HH */
index 655c36c..d32be04 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-map-private.hh"
-
+#include "hb-open-type.hh"
+#include "hb-ot-layout.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-map.hh"
+#include "hb-map.hh"
+
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
-
-// Just so we compile them; unused otherwise:
-#include "hb-ot-layout-base-table.hh"
-#include "hb-ot-layout-jstf-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-name-table.hh"
-#include "hb-map-private.hh"
-
-
-hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face)
-{
-  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
-  if (unlikely (!layout))
-    return nullptr;
-
-  layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
-  layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
+#include "hb-ot-os2-table.hh"
 
-  layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
-  layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
+#include "hb-aat-layout-lcar-table.hh"
+#include "hb-aat-layout-morx-table.hh"
 
-  layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
-  layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
 
-  layout->math.init (face);
-  layout->fvar.init (face);
-  layout->avar.init (face);
-
-  {
-    /*
-     * The ugly business of blacklisting individual fonts' tables happen here!
-     * See this thread for why we finally had to bend in and do this:
-     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-     */
-    unsigned int gdef_len = layout->gdef_blob->length;
-    unsigned int gsub_len = layout->gsub_blob->length;
-    unsigned int gpos_len = layout->gpos_blob->length;
-    if (0
-      /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
-      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
-      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
-      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
-      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
-      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
-      /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
-      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
-    )
-    {
-      /* In certain versions of Times New Roman Italic and Bold Italic,
-       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
-       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
-       * double-quote.  See:
-       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-       */
-     if (3 == layout->gdef->get_glyph_class (5))
-       layout->gdef = &Null(OT::GDEF);
-    }
-    else if (0
-      /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
-      || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
-      /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
-      || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
-      /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
-      || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
-      /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
-      || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
-      /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
-      /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
-      /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
-      || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
-      /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
-      || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
-      /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
-      /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
-      || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
-      /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
-      || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
-      || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
-      /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
-      || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
-      /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
-      || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
-      /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
-      || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
-      /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
-      || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
-      /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
-      /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
-      || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
-      /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
-      /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
-      || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
-      /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
-      || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
-      /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
-      || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
-      /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
-      || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
-      /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
-      || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
-      /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
-      || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
-      /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
-      || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
-      /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
-      || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
-      /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
-      || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
-      /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
-       *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
-      || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
-    )
-    {
-      /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
-       * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
-       * and the version of Cantarell shipped by Ubuntu 16.04.
-       * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
-       * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
-       */
-      layout->gdef = &Null(OT::GDEF);
-    }
-  }
+/**
+ * SECTION:hb-ot-layout
+ * @title: hb-ot-layout
+ * @short_description: OpenType Layout
+ * @include: hb-ot.h
+ *
+ * Functions for querying OpenType Layout features in the font face.
+ **/
 
-  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
-  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
 
-  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
+/*
+ * kern
+ */
 
-  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
-               (layout->gpos_lookup_count && !layout->gpos_accels)))
-  {
-    _hb_ot_layout_destroy (layout);
-    return nullptr;
-  }
+bool
+hb_ot_layout_has_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_data ();
+}
 
-  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
-  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
+bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_state_machine ();
+}
 
-  return layout;
+bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_cross_stream ();
 }
 
 void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout)
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                  hb_font_t *font,
+                  hb_buffer_t  *buffer)
 {
-  if (layout->gsub_accels)
-    for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-      layout->gsub_accels[i].fini ();
-  if (layout->gpos_accels)
-    for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-      layout->gpos_accels[i].fini ();
-
-  free (layout->gsub_accels);
-  free (layout->gpos_accels);
+  hb_blob_t *blob = font->face->table.kern.get_blob ();
+  const AAT::kern& kern = *blob->as<AAT::kern> ();
 
-  hb_blob_destroy (layout->gdef_blob);
-  hb_blob_destroy (layout->gsub_blob);
-  hb_blob_destroy (layout->gpos_blob);
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
-  layout->math.fini ();
-  layout->fvar.fini ();
-  layout->avar.fini ();
-
-  free (layout);
+  kern.apply (&c);
 }
 
-// static inline const OT::BASE&
-// _get_base (hb_face_t *face)
-// {
-//   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE);
-//   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-//   return *(layout->base.get ());
-// }
 
-static inline const OT::GDEF&
-_get_gdef (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
-  return *hb_ot_layout_from_face (face)->gdef;
-}
-static inline const OT::GSUB&
-_get_gsub (hb_face_t *face)
+/*
+ * GDEF
+ */
+
+bool
+OT::GDEF::is_blacklisted (hb_blob_t *blob,
+                         hb_face_t *face) const
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
-  return *hb_ot_layout_from_face (face)->gsub;
+  /* The ugly business of blacklisting individual fonts' tables happen here!
+   * See this thread for why we finally had to bend in and do this:
+   * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+   *
+   * In certain versions of Times New Roman Italic and Bold Italic,
+   * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
+   * in GDEF.  Many versions of Tahoma have bad GDEF tables that
+   * incorrectly classify some spacing marks such as certain IPA
+   * symbols as glyph class 3. So do older versions of Microsoft
+   * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
+   *
+   * Nuke the GDEF tables of to avoid unwanted width-zeroing.
+   *
+   * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
+   */
+#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
+  switch ENCODE(blob->length,
+               face->table.GSUB->table.get_length (),
+               face->table.GPOS->table.get_length ())
+  {
+    /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
+    case ENCODE (442, 2874, 42038):
+    /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
+    case ENCODE (430, 2874, 40662):
+    /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
+    case ENCODE (442, 2874, 39116):
+    /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
+    case ENCODE (430, 2874, 39374):
+    /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
+    case ENCODE (490, 3046, 41638):
+    /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
+    case ENCODE (478, 3046, 41902):
+    /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
+    case ENCODE (898, 12554, 46470):
+    /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
+    case ENCODE (910, 12566, 47732):
+    /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
+    case ENCODE (928, 23298, 59332):
+    /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
+    case ENCODE (940, 23310, 60732):
+    /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (964, 23836, 60072):
+    /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (976, 23832, 61456):
+    /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
+    case ENCODE (994, 24474, 60336):
+    /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
+    case ENCODE (1006, 24470, 61740):
+    /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1006, 24576, 61346):
+    /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1018, 24572, 62828):
+    /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
+    case ENCODE (1006, 24576, 61352):
+    /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
+    case ENCODE (1018, 24572, 62834):
+    /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
+    case ENCODE (832, 7324, 47162):
+    /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
+    case ENCODE (844, 7302, 45474):
+    /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
+    case ENCODE (180, 13054, 7254):
+    /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
+    case ENCODE (192, 12638, 7254):
+    /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
+    case ENCODE (192, 12690, 7254):
+    /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
+    /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
+    case ENCODE (188, 248, 3852):
+    /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
+    /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
+    case ENCODE (188, 264, 3426):
+    /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
+    case ENCODE (1058, 47032, 11818):
+    /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
+    case ENCODE (1046, 47030, 12600):
+    /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
+    case ENCODE (1058, 71796, 16770):
+    /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
+    case ENCODE (1046, 71790, 17862):
+    /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
+    case ENCODE (1046, 71788, 17112):
+    /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
+    case ENCODE (1058, 71794, 17514):
+    /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
+    case ENCODE (1330, 109904, 57938):
+    /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
+    case ENCODE (1330, 109904, 58972):
+    /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
+     *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+    case ENCODE (1004, 59092, 14836):
+      return true;
+#undef ENCODE
+  }
+  return false;
 }
-static inline const OT::GPOS&
-_get_gpos (hb_face_t *face)
+
+static void
+_hb_ot_layout_set_glyph_props (hb_font_t *font,
+                              hb_buffer_t *buffer)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
-  return *hb_ot_layout_from_face (face)->gpos;
+  _hb_buffer_assert_gsubgpos_vars (buffer);
+
+  const OT::GDEF &gdef = *font->face->table.GDEF->table;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
+    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+    buffer->info[i].syllable() = 0;
+  }
 }
 
-/*
- * GDEF
- */
+/* Public API */
 
 hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face)
 {
-  return _get_gdef (face).has_glyph_classes ();
+  return face->table.GDEF->table->has_glyph_classes ();
 }
 
 /**
@@ -265,7 +234,7 @@ hb_ot_layout_glyph_class_t
 hb_ot_layout_get_glyph_class (hb_face_t      *face,
                              hb_codepoint_t  glyph)
 {
-  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
+  return (hb_ot_layout_glyph_class_t) face->table.GDEF->table->get_glyph_class (glyph);
 }
 
 /**
@@ -278,7 +247,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
                                  hb_ot_layout_glyph_class_t  klass,
                                  hb_set_t                   *glyphs /* OUT */)
 {
-  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
+  return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
 }
 
 unsigned int
@@ -288,7 +257,10 @@ hb_ot_layout_get_attach_points (hb_face_t      *face,
                                unsigned int   *point_count /* IN/OUT */,
                                unsigned int   *point_array /* OUT */)
 {
-  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
+  return face->table.GDEF->table->get_attach_points (glyph,
+                                                    start_offset,
+                                                    point_count,
+                                                    point_array);
 }
 
 unsigned int
@@ -299,7 +271,15 @@ hb_ot_layout_get_ligature_carets (hb_font_t      *font,
                                  unsigned int   *caret_count /* IN/OUT */,
                                  hb_position_t  *caret_array /* OUT */)
 {
-  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  unsigned int result_caret_count = 0;
+  unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
+  if (result)
+  {
+    if (caret_count) *caret_count = result_caret_count;
+  }
+  else
+    result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  return result;
 }
 
 
@@ -307,13 +287,45 @@ hb_ot_layout_get_ligature_carets (hb_font_t      *font,
  * GSUB/GPOS
  */
 
+bool
+OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                         hb_face_t *face) const
+{
+  /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
+   * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
+   * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
+   * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
+   * to prefer it over morx because we want to be consistent with other OpenType
+   * shapers.
+   *
+   * To work around broken Indic Mac system fonts, we ignore GSUB table if
+   * OS/2 VendorId is 'MUTF' and font has morx table as well.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1410
+   * https://github.com/harfbuzz/harfbuzz/issues/1348
+   * https://github.com/harfbuzz/harfbuzz/issues/1391
+   */
+  if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
+               face->table.morx->has_data ()))
+    return true;
+
+  return false;
+}
+
+bool
+OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                         hb_face_t *face HB_UNUSED) const
+{
+  return false;
+}
+
 static const OT::GSUBGPOS&
 get_gsubgpos_table (hb_face_t *face,
                    hb_tag_t   table_tag)
 {
   switch (table_tag) {
-    case HB_OT_TAG_GSUB: return _get_gsub (face);
-    case HB_OT_TAG_GPOS: return _get_gpos (face);
+    case HB_OT_TAG_GSUB: return *face->table.GSUB->table;
+    case HB_OT_TAG_GPOS: return *face->table.GPOS->table;
     default:             return Null(OT::GSUBGPOS);
   }
 }
@@ -324,7 +336,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t    *face,
                                    hb_tag_t      table_tag,
                                    unsigned int  start_offset,
                                    unsigned int *script_count /* IN/OUT */,
-                                   hb_tag_t     *script_tags /* OUT */)
+                                   hb_tag_t     *script_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
@@ -370,17 +382,36 @@ hb_ot_layout_table_choose_script (hb_face_t      *face,
                                  unsigned int   *script_index,
                                  hb_tag_t       *chosen_script)
 {
+  const hb_tag_t *t;
+  for (t = script_tags; *t; t++);
+  return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script);
+}
+
+/**
+ * hb_ot_layout_table_select_script:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_table_select_script (hb_face_t      *face,
+                                 hb_tag_t        table_tag,
+                                 unsigned int    script_count,
+                                 const hb_tag_t *script_tags,
+                                 unsigned int   *script_index  /* OUT */,
+                                 hb_tag_t       *chosen_script /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  unsigned int i;
 
-  while (*script_tags)
+  for (i = 0; i < script_count; i++)
   {
-    if (g.find_script_index (*script_tags, script_index)) {
+    if (g.find_script_index (script_tags[i], script_index))
+    {
       if (chosen_script)
-        *chosen_script = *script_tags;
+        *chosen_script = script_tags[i];
       return true;
     }
-    script_tags++;
   }
 
   /* try finding 'DFLT' */
@@ -416,14 +447,14 @@ hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
                                     hb_tag_t      table_tag,
                                     unsigned int  start_offset,
                                     unsigned int *feature_count /* IN/OUT */,
-                                    hb_tag_t     *feature_tags /* OUT */)
+                                    hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
   return g.get_feature_tags (start_offset, feature_count, feature_tags);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_table_find_feature (hb_face_t    *face,
                                 hb_tag_t      table_tag,
                                 hb_tag_t      feature_tag,
@@ -452,7 +483,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t    *face,
                                       unsigned int  script_index,
                                       unsigned int  start_offset,
                                       unsigned int *language_count /* IN/OUT */,
-                                      hb_tag_t     *language_tags /* OUT */)
+                                      hb_tag_t     *language_tags  /* OUT */)
 {
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
 
@@ -466,13 +497,38 @@ hb_ot_layout_script_find_language (hb_face_t    *face,
                                   hb_tag_t      language_tag,
                                   unsigned int *language_index)
 {
+  return hb_ot_layout_script_select_language (face,
+                                             table_tag,
+                                             script_index,
+                                             1,
+                                             &language_tag,
+                                             language_index);
+}
+
+/**
+ * hb_ot_layout_script_select_language:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                    hb_tag_t        table_tag,
+                                    unsigned int    script_index,
+                                    unsigned int    language_count,
+                                    const hb_tag_t *language_tags,
+                                    unsigned int   *language_index /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), "");
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
+  unsigned int i;
 
-  if (s.find_lang_sys_index (language_tag, language_index))
-    return true;
+  for (i = 0; i < language_count; i++)
+  {
+    if (s.find_lang_sys_index (language_tags[i], language_index))
+      return true;
+  }
 
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
+  /* try finding 'dflt' */
   if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
     return false;
 
@@ -524,7 +580,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
                                           unsigned int  script_index,
                                           unsigned int  language_index,
                                           unsigned int  start_offset,
-                                          unsigned int *feature_count /* IN/OUT */,
+                                          unsigned int *feature_count   /* IN/OUT */,
                                           unsigned int *feature_indexes /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
@@ -540,7 +596,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
                                        unsigned int  language_index,
                                        unsigned int  start_offset,
                                        unsigned int *feature_count /* IN/OUT */,
-                                       hb_tag_t     *feature_tags /* OUT */)
+                                       hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
@@ -594,7 +650,7 @@ hb_ot_layout_feature_get_lookups (hb_face_t    *face,
                                  hb_tag_t      table_tag,
                                  unsigned int  feature_index,
                                  unsigned int  start_offset,
-                                 unsigned int *lookup_count /* IN/OUT */,
+                                 unsigned int *lookup_count   /* IN/OUT */,
                                  unsigned int *lookup_indexes /* OUT */)
 {
   return hb_ot_layout_feature_with_variations_get_lookups (face,
@@ -615,207 +671,202 @@ unsigned int
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                     hb_tag_t      table_tag)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0;
-  switch (table_tag)
-  {
-    case HB_OT_TAG_GSUB:
-    {
-      return hb_ot_layout_from_face (face)->gsub_lookup_count;
-    }
-    case HB_OT_TAG_GPOS:
-    {
-      return hb_ot_layout_from_face (face)->gpos_lookup_count;
-    }
-  }
-  return 0;
+  return get_gsubgpos_table (face, table_tag).get_lookup_count ();
 }
 
-static void
-_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
-                                      hb_tag_t        table_tag,
-                                      unsigned int    feature_index,
-                                      hb_set_t       *lookup_indexes /* OUT */)
+
+struct hb_collect_features_context_t
 {
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
-
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_get_lookups (face,
-                                     table_tag,
-                                     feature_index,
-                                     offset, &len,
-                                     lookup_indices);
-
-    for (unsigned int i = 0; i < len; i++)
-      lookup_indexes->add (lookup_indices[i]);
-
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
-}
+  hb_collect_features_context_t (hb_face_t       *face,
+                                hb_tag_t         table_tag,
+                                hb_set_t        *feature_indexes_)
+    : g (get_gsubgpos_table (face, table_tag)),
+      feature_indexes (feature_indexes_),
+      script_count(0),langsys_count(0) {}
+
+  bool visited (const OT::Script &s)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!s.has_default_lang_sys () &&
+                 !s.get_lang_sys_count ()))
+      return true;
+
+    if (script_count++ > HB_MAX_SCRIPTS)
+      return true;
+
+    return visited (s, visited_script);
+  }
+  bool visited (const OT::LangSys &l)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!l.has_required_feature () &&
+                 !l.get_feature_count ()))
+      return true;
+
+    if (langsys_count++ > HB_MAX_LANGSYS)
+      return true;
+
+    return visited (l, visited_langsys);
+  }
+
+  private:
+  template <typename T>
+  bool visited (const T &p, hb_set_t &visited_set)
+  {
+    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g);
+     if (visited_set.has (delta))
+      return true;
+
+    visited_set.add (delta);
+    return false;
+  }
+
+  public:
+  const OT::GSUBGPOS &g;
+  hb_set_t           *feature_indexes;
+
+  private:
+  hb_set_t visited_script;
+  hb_set_t visited_langsys;
+  unsigned int script_count;
+  unsigned int langsys_count;
+};
 
 static void
-_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
-                                       hb_tag_t        table_tag,
-                                       unsigned int    script_index,
-                                       unsigned int    language_index,
-                                       const hb_tag_t *features,
-                                       hb_set_t       *lookup_indexes /* OUT */)
+langsys_collect_features (hb_collect_features_context_t *c,
+                         const OT::LangSys  &l,
+                         const hb_tag_t     *features)
 {
+  if (c->visited (l)) return;
+
   if (!features)
   {
-    unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature (face,
-                                                   table_tag,
-                                                   script_index,
-                                                   language_index,
-                                                   &required_feature_index,
-                                                   nullptr))
-      _hb_ot_layout_collect_lookups_lookups (face,
-                                            table_tag,
-                                            required_feature_index,
-                                            lookup_indexes);
-
-    /* All features */
-    unsigned int feature_indices[32];
-    unsigned int offset, len;
-
-    offset = 0;
-    do {
-      len = ARRAY_LENGTH (feature_indices);
-      hb_ot_layout_language_get_feature_indexes (face,
-                                                table_tag,
-                                                script_index,
-                                                language_index,
-                                                offset, &len,
-                                                feature_indices);
-
-      for (unsigned int i = 0; i < len; i++)
-       _hb_ot_layout_collect_lookups_lookups (face,
-                                              table_tag,
-                                              feature_indices[i],
-                                              lookup_indexes);
-
-      offset += len;
-    } while (len == ARRAY_LENGTH (feature_indices));
+    /* All features. */
+    if (l.has_required_feature ())
+      c->feature_indexes->add (l.get_required_feature_index ());
+
+    l.add_feature_indexes_to (c->feature_indexes);
   }
   else
   {
+    /* Ugh. Any faster way? */
     for (; *features; features++)
     {
-      unsigned int feature_index;
-      if (hb_ot_layout_language_find_feature (face,
-                                             table_tag,
-                                             script_index,
-                                             language_index,
-                                             *features,
-                                             &feature_index))
-        _hb_ot_layout_collect_lookups_lookups (face,
-                                              table_tag,
-                                              feature_index,
-                                              lookup_indexes);
+      hb_tag_t feature_tag = *features;
+      unsigned int num_features = l.get_feature_count ();
+      for (unsigned int i = 0; i < num_features; i++)
+      {
+       unsigned int feature_index = l.get_feature_index (i);
+
+       if (feature_tag == c->g.get_feature_tag (feature_index))
+       {
+         c->feature_indexes->add (feature_index);
+         break;
+       }
+      }
     }
   }
 }
 
 static void
-_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
-                                        hb_tag_t        table_tag,
-                                        unsigned int    script_index,
-                                        const hb_tag_t *languages,
-                                        const hb_tag_t *features,
-                                        hb_set_t       *lookup_indexes /* OUT */)
+script_collect_features (hb_collect_features_context_t *c,
+                        const OT::Script   &s,
+                        const hb_tag_t *languages,
+                        const hb_tag_t *features)
 {
-  _hb_ot_layout_collect_lookups_features (face,
-                                         table_tag,
-                                         script_index,
-                                         HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
-                                         features,
-                                         lookup_indexes);
+  if (c->visited (s)) return;
 
   if (!languages)
   {
-    /* All languages */
-    unsigned int count = hb_ot_layout_script_get_language_tags (face,
-                                                               table_tag,
-                                                               script_index,
-                                                               0, nullptr, nullptr);
+    /* All languages. */
+    if (s.has_default_lang_sys ())
+      langsys_collect_features (c,
+                               s.get_default_lang_sys (),
+                               features);
+
+    unsigned int count = s.get_lang_sys_count ();
     for (unsigned int language_index = 0; language_index < count; language_index++)
-      _hb_ot_layout_collect_lookups_features (face,
-                                             table_tag,
-                                             script_index,
-                                             language_index,
-                                             features,
-                                             lookup_indexes);
+      langsys_collect_features (c,
+                               s.get_lang_sys (language_index),
+                               features);
   }
   else
   {
     for (; *languages; languages++)
     {
       unsigned int language_index;
-      if (hb_ot_layout_script_find_language (face,
-                                            table_tag,
-                                            script_index,
-                                            *languages,
-                                            &language_index))
-        _hb_ot_layout_collect_lookups_features (face,
-                                               table_tag,
-                                               script_index,
-                                               language_index,
-                                               features,
-                                               lookup_indexes);
+      if (s.find_lang_sys_index (*languages, &language_index))
+       langsys_collect_features (c,
+                                 s.get_lang_sys (language_index),
+                                 features);
     }
   }
 }
 
 /**
- * hb_ot_layout_collect_lookups:
+ * hb_ot_layout_collect_features:
  *
- * Since: 0.9.8
+ * Since: 1.8.5
  **/
 void
-hb_ot_layout_collect_lookups (hb_face_t      *face,
-                             hb_tag_t        table_tag,
-                             const hb_tag_t *scripts,
-                             const hb_tag_t *languages,
-                             const hb_tag_t *features,
-                             hb_set_t       *lookup_indexes /* OUT */)
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */)
 {
+  hb_collect_features_context_t c (face, table_tag, feature_indexes);
   if (!scripts)
   {
-    /* All scripts */
-    unsigned int count = hb_ot_layout_table_get_script_tags (face,
-                                                            table_tag,
-                                                            0, nullptr, nullptr);
+    /* All scripts. */
+    unsigned int count = c.g.get_script_count ();
     for (unsigned int script_index = 0; script_index < count; script_index++)
-      _hb_ot_layout_collect_lookups_languages (face,
-                                              table_tag,
-                                              script_index,
-                                              languages,
-                                              features,
-                                              lookup_indexes);
+      script_collect_features (&c,
+                              c.g.get_script (script_index),
+                              languages,
+                              features);
   }
   else
   {
     for (; *scripts; scripts++)
     {
       unsigned int script_index;
-      if (hb_ot_layout_table_find_script (face,
-                                         table_tag,
-                                         *scripts,
-                                         &script_index))
-        _hb_ot_layout_collect_lookups_languages (face,
-                                                table_tag,
-                                                script_index,
-                                                languages,
-                                                features,
-                                                lookup_indexes);
+      if (c.g.find_script_index (*scripts, &script_index))
+       script_collect_features (&c,
+                                c.g.get_script (script_index),
+                                languages,
+                                features);
     }
   }
 }
 
 /**
+ * hb_ot_layout_collect_lookups:
+ *
+ * Since: 0.9.8
+ **/
+void
+hb_ot_layout_collect_lookups (hb_face_t      *face,
+                             hb_tag_t        table_tag,
+                             const hb_tag_t *scripts,
+                             const hb_tag_t *languages,
+                             const hb_tag_t *features,
+                             hb_set_t       *lookup_indexes /* OUT */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_set_t feature_indexes;
+  hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
+
+  for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
+       hb_set_next (&feature_indexes, &feature_index);)
+    g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
+}
+
+/**
  * hb_ot_layout_lookup_collect_glyphs:
  *
  * Since: 0.9.7
@@ -824,13 +875,11 @@ void
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                    hb_tag_t      table_tag,
                                    unsigned int  lookup_index,
-                                   hb_set_t     *glyphs_before, /* OUT. May be nullptr */
-                                   hb_set_t     *glyphs_input,  /* OUT. May be nullptr */
-                                   hb_set_t     *glyphs_after,  /* OUT. May be nullptr */
-                                   hb_set_t     *glyphs_output  /* OUT. May be nullptr */)
+                                   hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_output  /* OUT.  May be NULL */)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
-
   OT::hb_collect_glyphs_context_t c (face,
                                     glyphs_before,
                                     glyphs_input,
@@ -841,13 +890,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
   {
     case HB_OT_TAG_GSUB:
     {
-      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+      const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
     case HB_OT_TAG_GPOS:
     {
-      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
+      const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
@@ -894,7 +943,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
 hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face)
 {
-  return &_get_gsub (face) != &Null(OT::GSUB);
+  return face->table.GSUB->table->has_data ();
 }
 
 /**
@@ -909,29 +958,82 @@ hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
                                      unsigned int          glyphs_length,
                                      hb_bool_t             zero_context)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
-  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
+  return hb_ot_layout_lookup_would_substitute_fast (face,
+                                                   lookup_index,
+                                                   glyphs, glyphs_length,
+                                                   zero_context);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
                                           unsigned int          lookup_index,
                                           const hb_codepoint_t *glyphs,
                                           unsigned int          glyphs_length,
-                                          hb_bool_t             zero_context)
+                                          bool                  zero_context)
 {
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
+  if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
   OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
 
-  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
+  return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
 }
 
 void
-hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                              hb_buffer_t  *buffer)
 {
-  OT::GSUB::substitute_start (font, buffer);
+_hb_ot_layout_set_glyph_props (font, buffer);
+}
+
+void
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                   bool (*filter) (const hb_glyph_info_t *info))
+{
+  /* Merge clusters and delete filtered glyphs.
+   * NOTE! We can't use out-buffer as we have positioning data. */
+  unsigned int j = 0;
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    if (filter (&info[i]))
+    {
+      /* Merge clusters.
+       * Same logic as buffer->delete_glyph(), but for in-place removal. */
+
+      unsigned int cluster = info[i].cluster;
+      if (i + 1 < count && cluster == info[i + 1].cluster)
+       continue; /* Cluster survives; do nothing. */
+
+      if (j)
+      {
+       /* Merge cluster backward. */
+       if (cluster < info[j - 1].cluster)
+       {
+         unsigned int mask = info[i].mask;
+         unsigned int old_cluster = info[j - 1].cluster;
+         for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+           buffer->set_cluster (info[k - 1], cluster, mask);
+       }
+       continue;
+      }
+
+      if (i + 1 < count)
+       buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+      continue;
+    }
+
+    if (j != i)
+    {
+      info[j] = info[i];
+      pos[j] = pos[i];
+    }
+    j++;
+  }
+  buffer->len = j;
 }
 
 /**
@@ -944,10 +1046,10 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
                                        unsigned int  lookup_index,
                                        hb_set_t     *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
 
-  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
   l.closure (&c, lookup_index);
 }
@@ -965,10 +1067,11 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
                                          const hb_set_t *lookups,
                                          hb_set_t       *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
-  const OT::GSUB& gsub = _get_gsub (face);
+  const OT::GSUB& gsub = *face->table.GSUB->table;
 
+  unsigned int iteration_count = 0;
   unsigned int glyphs_length;
   do
   {
@@ -983,7 +1086,8 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
       for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
         gsub.get_lookup (i).closure (&c, i);
     }
-  } while (glyphs_length != glyphs->get_population ());
+  } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
+          glyphs_length != glyphs->get_population ());
 }
 
 /*
@@ -993,7 +1097,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
 hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face)
 {
-  return &_get_gpos (face) != &Null(OT::GPOS);
+  return face->table.GPOS->table->has_data ();
 }
 
 void
@@ -1020,14 +1124,14 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
  * Since: 0.9.10
  **/
 hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                             unsigned int *design_size,       /* OUT.  May be nullptr */
-                             unsigned int *subfamily_id,      /* OUT.  May be nullptr */
-                             unsigned int *subfamily_name_id, /* OUT.  May be nullptr */
-                             unsigned int *range_start,       /* OUT.  May be nullptr */
-                             unsigned int *range_end          /* OUT.  May be nullptr */)
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                             unsigned int    *design_size,       /* OUT.  May be NULL */
+                             unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                             hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                             unsigned int    *range_start,       /* OUT.  May be NULL */
+                             unsigned int    *range_end          /* OUT.  May be NULL */)
 {
-  const OT::GPOS &gpos = _get_gpos (face);
+  const OT::GPOS &gpos = *face->table.GPOS->table;
   const hb_tag_t tag = HB_TAG ('s','i','z','e');
 
   unsigned int num_features = gpos.get_feature_count ();
@@ -1040,30 +1144,152 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 
       if (params.designSize)
       {
-#define PARAM(a, A) if (a) *a = params.A
-       PARAM (design_size, designSize);
-       PARAM (subfamily_id, subfamilyID);
-       PARAM (subfamily_name_id, subfamilyNameID);
-       PARAM (range_start, rangeStart);
-       PARAM (range_end, rangeEnd);
-#undef PARAM
+       if (design_size) *design_size = params.designSize;
+       if (subfamily_id) *subfamily_id = params.subfamilyID;
+       if (subfamily_name_id) *subfamily_name_id = params.subfamilyNameID;
+       if (range_start) *range_start = params.rangeStart;
+       if (range_end) *range_end = params.rangeEnd;
 
        return true;
       }
     }
   }
 
-#define PARAM(a, A) if (a) *a = 0
-  PARAM (design_size, designSize);
-  PARAM (subfamily_id, subfamilyID);
-  PARAM (subfamily_name_id, subfamilyNameID);
-  PARAM (range_start, rangeStart);
-  PARAM (range_end, rangeEnd);
-#undef PARAM
+  if (design_size) *design_size = 0;
+  if (subfamily_id) *subfamily_id = 0;
+  if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
+  if (range_start) *range_start = 0;
+  if (range_end) *range_end = 0;
 
   return false;
 }
 
+/**
+ * hb_ot_layout_feature_get_name_ids:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *            for a user-interface label for this feature. (May be NULL.)
+ * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *              that an application can use for tooltip text for this
+ *              feature. (May be NULL.)
+ * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text
+ *             that illustrates the effect of this feature. (May be NULL.)
+ * @num_named_parameters: (out) (allow-none):  Number of named parameters. (May be zero.)
+ * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify
+ *                  strings for user-interface labels for the feature
+ *                  parameters. (Must be zero if numParameters is zero.)
+ *
+ * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
+ * "Character Variant" ('cvXX') features.
+ *
+ * Return value: true if data found, false otherwise
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                  hb_tag_t         table_tag,
+                                  unsigned int     feature_index,
+                                  hb_ot_name_id_t *label_id,             /* OUT.  May be NULL */
+                                  hb_ot_name_id_t *tooltip_id,           /* OUT.  May be NULL */
+                                  hb_ot_name_id_t *sample_id,            /* OUT.  May be NULL */
+                                  unsigned int    *num_named_parameters, /* OUT.  May be NULL */
+                                  hb_ot_name_id_t *first_param_id        /* OUT.  May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+  if (&feature_params != &Null (OT::FeatureParams))
+  {
+    const OT::FeatureParamsStylisticSet& ss_params =
+      feature_params.get_stylistic_set_params (feature_tag);
+    if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */
+    {
+      if (label_id) *label_id = ss_params.uiNameID;
+      // ssXX features don't have the rest
+      if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+      if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+      if (num_named_parameters) *num_named_parameters = 0;
+      if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+      return true;
+    }
+    const OT::FeatureParamsCharacterVariants& cv_params =
+      feature_params.get_character_variants_params (feature_tag);
+    if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */
+    {
+      if (label_id) *label_id = cv_params.featUILableNameID;
+      if (tooltip_id) *tooltip_id = cv_params.featUITooltipTextNameID;
+      if (sample_id) *sample_id = cv_params.sampleTextNameID;
+      if (num_named_parameters) *num_named_parameters = cv_params.numNamedParameters;
+      if (first_param_id) *first_param_id = cv_params.firstParamUILabelNameID;
+      return true;
+    }
+  }
+
+  if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
+  if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+  if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+  if (num_named_parameters) *num_named_parameters = 0;
+  if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+  return false;
+}
+
+/**
+ * hb_ot_layout_feature_get_characters:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @start_offset: In case the resulting char_count was equal to its input value, there
+ *                is a chance there were more characters on the tag so this API can be
+ *                called with an offset till resulting char_count gets to a number
+ *                lower than input buffer (or consider using just a bigger buffer for
+ *                one shot copying).
+ * @char_count: (inout) (allow-none): The count of characters for which this feature
+ *              provides glyph variants. (May be zero.)
+ * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints
+ *              of the characters for which this feature provides glyph variants.
+ *
+ * Fetches characters listed by designer under feature parameters for "Character
+ * Variant" ("cvXX") features.
+ *
+ * Return value: Number of total sample characters in the cvXX feature.
+ *
+ * Since: 2.0.0
+ **/
+unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                    hb_tag_t        table_tag,
+                                    unsigned int    feature_index,
+                                    unsigned int    start_offset,
+                                    unsigned int   *char_count, /* IN/OUT.  May be NULL */
+                                    hb_codepoint_t *characters  /* OUT.     May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+
+  const OT::FeatureParamsCharacterVariants& cv_params =
+    feature_params.get_character_variants_params(feature_tag);
+
+  unsigned int len = 0;
+  if (char_count && characters && start_offset < cv_params.characters.len)
+  {
+    len = MIN (cv_params.characters.len - start_offset, *char_count);
+    for (unsigned int i = 0; i < len; ++i)
+      characters[i] = cv_params.characters[start_offset + i];
+  }
+  if (char_count) *char_count = len;
+  return cv_params.characters.len;
+}
+
 
 /*
  * Parts of different types are implemented here such that they have direct
@@ -1073,86 +1299,36 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 
 struct GSUBProxy
 {
-  static const unsigned int table_index = 0;
-  static const bool inplace = false;
+  static constexpr unsigned table_index = 0u;
+  static constexpr bool inplace = false;
   typedef OT::SubstLookup Lookup;
 
   GSUBProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gsub),
-    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
+    table (*face->table.GSUB->table),
+    accels (face->table.GSUB->accels) {}
 
   const OT::GSUB &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 struct GPOSProxy
 {
-  static const unsigned int table_index = 1;
-  static const bool inplace = true;
+  static constexpr unsigned table_index = 1u;
+  static constexpr bool inplace = true;
   typedef OT::PosLookup Lookup;
 
   GPOSProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gpos),
-    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
+    table (*face->table.GPOS->table),
+    accels (face->table.GPOS->accels) {}
 
   const OT::GPOS &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 
-struct hb_get_subtables_context_t :
-       OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
-{
-  template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-  {
-    const Type *typed_obj = (const Type *) obj;
-    return typed_obj->apply (c);
-  }
-
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
-
-  struct hb_applicable_t
-  {
-    inline void init (const void *obj_, hb_apply_func_t apply_func_)
-    {
-      obj = obj_;
-      apply_func = apply_func_;
-    }
-
-    inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
-
-    private:
-    const void *obj;
-    hb_apply_func_t apply_func;
-  };
-
-  typedef hb_auto_t<hb_vector_t<hb_applicable_t> > array_t;
-
-  /* Dispatch interface. */
-  inline const char *get_name (void) { return "GET_SUBTABLES"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj)
-  {
-    hb_applicable_t *entry = array.push();
-    entry->init (&obj, apply_to<T>);
-    return HB_VOID;
-  }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-
-  hb_get_subtables_context_t (array_t &array_) :
-                             array (array_),
-                             debug_depth (0) {}
-
-  array_t &array;
-  unsigned int debug_depth;
-};
-
 static inline bool
 apply_forward (OT::hb_ot_apply_context_t *c,
-              const hb_ot_layout_lookup_accelerator_t &accel,
-              const hb_get_subtables_context_t::array_t &subtables)
+              const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1163,12 +1339,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
        (buffer->cur().mask & c->lookup_mask) &&
        c->check_glyph_property (&buffer->cur(), c->lookup_props))
      {
-       for (unsigned int i = 0; i < subtables.len; i++)
-         if (subtables[i].apply (c))
-        {
-          applied = true;
-          break;
-        }
+       applied = accel.apply (c);
      }
 
     if (applied)
@@ -1181,8 +1352,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
 
 static inline bool
 apply_backward (OT::hb_ot_apply_context_t *c,
-              const hb_ot_layout_lookup_accelerator_t &accel,
-              const hb_get_subtables_context_t::array_t &subtables)
+              const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1191,14 +1361,8 @@ apply_backward (OT::hb_ot_apply_context_t *c,
     if (accel.may_have (buffer->cur().codepoint) &&
        (buffer->cur().mask & c->lookup_mask) &&
        c->check_glyph_property (&buffer->cur(), c->lookup_props))
-    {
-     for (unsigned int i = 0; i < subtables.len; i++)
-       if (subtables[i].apply (c))
-       {
-        ret = true;
-        break;
-       }
-    }
+     ret |= accel.apply (c);
+
     /* The reverse lookup doesn't "advance" cursor (for good reason). */
     buffer->idx--;
 
@@ -1211,7 +1375,7 @@ template <typename Proxy>
 static inline void
 apply_string (OT::hb_ot_apply_context_t *c,
              const typename Proxy::Lookup &lookup,
-             const hb_ot_layout_lookup_accelerator_t &accel)
+             const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -1220,19 +1384,15 @@ apply_string (OT::hb_ot_apply_context_t *c,
 
   c->set_lookup_props (lookup.get_props ());
 
-  hb_get_subtables_context_t::array_t subtables;
-  hb_get_subtables_context_t c_get_subtables (subtables);
-  lookup.dispatch (&c_get_subtables);
-
   if (likely (!lookup.is_reverse ()))
   {
     /* in/out forward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->clear_output ();
     buffer->idx = 0;
 
     bool ret;
-    ret = apply_forward (c, accel, subtables);
+    ret = apply_forward (c, accel);
     if (ret)
     {
       if (!Proxy::inplace)
@@ -1244,11 +1404,11 @@ apply_string (OT::hb_ot_apply_context_t *c,
   else
   {
     /* in-place backward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->remove_output ();
     buffer->idx = buffer->len - 1;
 
-    apply_backward (c, accel, subtables);
+    apply_backward (c, accel);
   }
 }
 
@@ -1263,7 +1423,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
   OT::hb_ot_apply_context_t c (table_index, font, buffer);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
+  for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) {
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     {
@@ -1273,6 +1433,11 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
+      if (lookups[table_index][i].random)
+      {
+       c.set_random (true);
+       buffer->unsafe_to_break_all ();
+      }
       apply_string<Proxy> (&c,
                           proxy.table.get_lookup (lookup_index),
                           proxy.accels[lookup_index]);
@@ -1302,31 +1467,65 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
 void
 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
                                const OT::SubstLookup &lookup,
-                               const hb_ot_layout_lookup_accelerator_t &accel)
+                               const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
 
+#if 0
+static const OT::BASE& _get_base (hb_face_t *face)
+{
+  return *face->table.BASE;
+}
 
+hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                          hb_ot_layout_baseline_t  baseline,
+                          hb_direction_t           direction,
+                          hb_tag_t                 script_tag,
+                          hb_tag_t                 language_tag,
+                          hb_position_t           *coord        /* OUT.  May be NULL. */)
+{
+  const OT::BASE &base = _get_base (font->face);
+  bool result = base.get_baseline (font, baseline, direction, script_tag,
+                                  language_tag, coord);
 
+  /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
+  if (!result && coord) *coord = 0;
 
+  if (coord) *coord = font->em_scale_dir (*coord, direction);
+
+  return result;
+}
+
+/* To be moved to public header */
 /*
- * OT::BASE
+ * BASE
  */
 
-// /**
-//  * hb_ot_base_has_data:
-//  * @face: #hb_face_t to test
-//  *
-//  * This function allows to verify the presence of an OpenType BASE table on the
-//  * face.
-//  *
-//  * Return value: true if face has a BASE table, false otherwise
-//  *
-//  * Since: XXX
-//  **/
-// hb_bool_t
-// hb_ot_base_has_data (hb_face_t *face)
-// {
-//   return &_get_base (face) != &Null(OT::BASE);
-// }
+/**
+ * hb_ot_layout_baseline_t:
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
+ *
+ * Since: DONTREPLACEME
+ */
+typedef enum {
+  HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'),
+  HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'),
+  HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'),
+  HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
+  HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
+  HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
+  HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
+} hb_ot_layout_baseline_t;
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                          hb_ot_layout_baseline_t  baseline,
+                          hb_direction_t           direction,
+                          hb_tag_t                 script_tag,
+                          hb_tag_t                 language_tag,
+                          hb_position_t           *coord        /* OUT.  May be NULL. */);
+
+#endif
index 0278796..e473954 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "hb.h"
 
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 
 HB_BEGIN_DECLS
 
@@ -46,6 +46,47 @@ HB_BEGIN_DECLS
 
 
 /*
+ * Script & Language tags.
+ */
+
+#define HB_OT_TAG_DEFAULT_SCRIPT       HB_TAG ('D', 'F', 'L', 'T')
+#define HB_OT_TAG_DEFAULT_LANGUAGE     HB_TAG ('d', 'f', 'l', 't')
+
+/**
+ * HB_OT_MAX_TAGS_PER_SCRIPT:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_SCRIPT      3u
+/**
+ * HB_OT_MAX_TAGS_PER_LANGUAGE:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_LANGUAGE    3u
+
+HB_EXTERN void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                    hb_language_t language,
+                                    unsigned int *script_count /* IN/OUT */,
+                                    hb_tag_t     *script_tags /* OUT */,
+                                    unsigned int *language_count /* IN/OUT */,
+                                    hb_tag_t     *language_tags /* OUT */);
+
+HB_EXTERN hb_script_t
+hb_ot_tag_to_script (hb_tag_t tag);
+
+HB_EXTERN hb_language_t
+hb_ot_tag_to_language (hb_tag_t tag);
+
+HB_EXTERN void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                  hb_tag_t       language_tag,
+                                  hb_script_t   *script /* OUT */,
+                                  hb_language_t *language /* OUT */);
+
+
+/*
  * GDEF
  */
 
@@ -111,13 +152,13 @@ hb_ot_layout_table_find_script (hb_face_t    *face,
                                hb_tag_t      script_tag,
                                unsigned int *script_index);
 
-/* Like find_script, but takes zero-terminated array of scripts to test */
 HB_EXTERN hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
+hb_ot_layout_table_select_script (hb_face_t      *face,
                                  hb_tag_t        table_tag,
+                                 unsigned int    script_count,
                                  const hb_tag_t *script_tags,
-                                 unsigned int   *script_index,
-                                 hb_tag_t       *chosen_script);
+                                 unsigned int   *script_index /* OUT */,
+                                 hb_tag_t       *chosen_script /* OUT */);
 
 HB_EXTERN unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
@@ -135,11 +176,12 @@ hb_ot_layout_script_get_language_tags (hb_face_t    *face,
                                       hb_tag_t     *language_tags /* OUT */);
 
 HB_EXTERN hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-                                  hb_tag_t      table_tag,
-                                  unsigned int  script_index,
-                                  hb_tag_t      language_tag,
-                                  unsigned int *language_index);
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                    hb_tag_t        table_tag,
+                                    unsigned int    script_index,
+                                    unsigned int    language_count,
+                                    const hb_tag_t *language_tags,
+                                    unsigned int   *language_index /* OUT */);
 
 HB_EXTERN hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
@@ -194,6 +236,13 @@ HB_EXTERN unsigned int
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                     hb_tag_t      table_tag);
 
+HB_EXTERN void
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */);
 
 HB_EXTERN void
 hb_ot_layout_collect_lookups (hb_face_t      *face,
@@ -207,10 +256,10 @@ HB_EXTERN void
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                    hb_tag_t      table_tag,
                                    unsigned int  lookup_index,
-                                   hb_set_t     *glyphs_before, /* OUT. May be NULL */
-                                   hb_set_t     *glyphs_input,  /* OUT. May be NULL */
-                                   hb_set_t     *glyphs_after,  /* OUT. May be NULL */
-                                   hb_set_t     *glyphs_output  /* OUT. May be NULL */);
+                                   hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                   hb_set_t     *glyphs_output  /* OUT.  May be NULL */);
 
 #ifdef HB_NOT_IMPLEMENTED
 typedef struct
@@ -315,29 +364,32 @@ Xhb_ot_layout_lookup_position (hb_font_t            *font,
 /* Optical 'size' feature info.  Returns true if found.
  * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
 HB_EXTERN hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                             unsigned int *design_size,       /* OUT.  May be NULL */
-                             unsigned int *subfamily_id,      /* OUT.  May be NULL */
-                             unsigned int *subfamily_name_id, /* OUT.  May be NULL */
-                             unsigned int *range_start,       /* OUT.  May be NULL */
-                             unsigned int *range_end          /* OUT.  May be NULL */);
-
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                             unsigned int    *design_size,       /* OUT.  May be NULL */
+                             unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                             hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                             unsigned int    *range_start,       /* OUT.  May be NULL */
+                             unsigned int    *range_end          /* OUT.  May be NULL */);
 
-/*
- * BASE
- */
-#if 0
 
-#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
-#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
-#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
-#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
-#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
-#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
-#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
+HB_EXTERN hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                  hb_tag_t         table_tag,
+                                  unsigned int     feature_index,
+                                  hb_ot_name_id_t *label_id             /* OUT.  May be NULL */,
+                                  hb_ot_name_id_t *tooltip_id           /* OUT.  May be NULL */,
+                                  hb_ot_name_id_t *sample_id            /* OUT.  May be NULL */,
+                                  unsigned int    *num_named_parameters /* OUT.  May be NULL */,
+                                  hb_ot_name_id_t *first_param_id       /* OUT.  May be NULL */);
 
-#endif
 
+HB_EXTERN unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                    hb_tag_t        table_tag,
+                                    unsigned int    feature_index,
+                                    unsigned int    start_offset,
+                                    unsigned int   *char_count    /* IN/OUT.  May be NULL */,
+                                    hb_codepoint_t *characters    /* OUT.     May be NULL */);
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh
new file mode 100644 (file)
index 0000000..a00b940
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,2013  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
+ */
+
+#ifndef HB_OT_LAYOUT_HH
+#define HB_OT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-shape.hh"
+#include "hb-set-digest.hh"
+
+
+struct hb_ot_shape_plan_t;
+
+
+/*
+ * kern
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_has_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face);
+
+HB_INTERNAL void
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                  hb_font_t *font,
+                  hb_buffer_t  *buffer);
+
+
+/* Private API corresponding to hb-ot-layout.h: */
+
+HB_INTERNAL bool
+hb_ot_layout_table_find_feature (hb_face_t    *face,
+                                hb_tag_t      table_tag,
+                                hb_tag_t      feature_tag,
+                                unsigned int *feature_index);
+
+
+/*
+ * GDEF
+ */
+
+enum hb_ot_layout_glyph_props_flags_t
+{
+  /* The following three match LookupFlags::Ignore* numbers. */
+  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH  = 0x02u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE    = 0x04u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MARK                = 0x08u,
+
+  /* The following are used internally; not derived from GDEF. */
+  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED     = 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED  = 0x40u,
+
+  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
+                                         HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                                         HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
+};
+HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
+
+
+/*
+ * GSUB/GPOS
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
+                                          unsigned int          lookup_index,
+                                          const hb_codepoint_t *glyphs,
+                                          unsigned int          glyphs_length,
+                                          bool                  zero_context);
+
+
+/* Should be called before all the substitute_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                              hb_buffer_t  *buffer);
+
+HB_INTERNAL void
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                   bool (*filter) (const hb_glyph_info_t *info));
+
+namespace OT {
+  struct hb_ot_apply_context_t;
+  struct SubstLookup;
+  struct hb_ot_layout_lookup_accelerator_t;
+}
+
+HB_INTERNAL void
+hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
+                               const OT::SubstLookup &lookup,
+                               const OT::hb_ot_layout_lookup_accelerator_t &accel);
+
+
+/* Should be called before all the position_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_position_start (hb_font_t    *font,
+                            hb_buffer_t  *buffer);
+
+/* Should be called after all the position_lookup's are done, to fini advances. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_advances (hb_font_t    *font,
+                                      hb_buffer_t  *buffer);
+
+/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_offsets (hb_font_t    *font,
+                                     hb_buffer_t  *buffer);
+
+
+/*
+ * Buffer var routines.
+ */
+
+/* buffer var allocations, used during the entire shaping process */
+#define unicode_props()                var2.u16[0]
+
+/* buffer var allocations, used during the GSUB/GPOS processing */
+#define glyph_props()          var1.u16[0] /* GDEF glyph properties */
+#define lig_props()            var1.u8[2] /* GSUB/GPOS ligature tracking */
+#define syllable()             var1.u8[3] /* GSUB/GPOS shaping boundaries */
+
+
+/* Loop over syllables. Based on foreach_cluster(). */
+#define foreach_syllable(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_syllable (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_syllable (buffer, start))
+
+static inline unsigned int
+_hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int syllable = info[start].syllable();
+  while (++start < count && syllable == info[start].syllable())
+    ;
+
+  return start;
+}
+
+
+/* unicode_props */
+
+/* Design:
+ * unicode_props() is a two-byte number.  The low byte includes:
+ * - General_Category: 5 bits.
+ * - A bit each for:
+ *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
+ *   * Whether it's one of the three Mongolian Free Variation Selectors,
+ *     CGJ, or other characters that are hidden but should not be ignored
+ *     like most other Default_Ignorable()s do during matching.
+ *   * Whether it's a grapheme continuation.
+ *
+ * The high-byte has different meanings, switched by the Gen-Cat:
+ * - For Mn,Mc,Me: the modified Combining_Class.
+ * - For Cf: whether it's ZWJ, ZWNJ, or something else.
+ * - For Ws: index of which space character this is, if space fallback
+ *   is needed, ie. we don't set this by default, only if asked to.
+ */
+
+enum hb_unicode_props_flags_t {
+  UPROPS_MASK_GEN_CAT  = 0x001Fu,
+  UPROPS_MASK_IGNORABLE        = 0x0020u,
+  UPROPS_MASK_HIDDEN   = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
+  UPROPS_MASK_CONTINUATION=0x0080u,
+
+  /* If GEN_CAT=FORMAT, top byte masks: */
+  UPROPS_MASK_Cf_ZWJ   = 0x0100u,
+  UPROPS_MASK_Cf_ZWNJ  = 0x0200u
+};
+HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
+
+static inline void
+_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
+{
+  hb_unicode_funcs_t *unicode = buffer->unicode;
+  unsigned int u = info->codepoint;
+  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
+  unsigned int props = gen_cat;
+
+  if (u >= 0x80)
+  {
+    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
+
+    if (unlikely (unicode->is_default_ignorable (u)))
+    {
+      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
+      props |=  UPROPS_MASK_IGNORABLE;
+      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
+      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
+      /* Mongolian Free Variation Selectors need to be remembered
+       * because although we need to hide them like default-ignorables,
+       * they need to non-ignorable during shaping.  This is similar to
+       * what we do for joiners in Indic-like shapers, but since the
+       * FVSes are GC=Mn, we have use a separate bit to remember them.
+       * Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/234 */
+      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
+      /* TAG characters need similar treatment. Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/463 */
+      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
+      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
+       * https://github.com/harfbuzz/harfbuzz/issues/554 */
+      else if (unlikely (u == 0x034Fu))
+      {
+       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
+       props |= UPROPS_MASK_HIDDEN;
+      }
+    }
+
+    if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (gen_cat)))
+    {
+      props |= UPROPS_MASK_CONTINUATION;
+      props |= unicode->modified_combining_class (u)<<8;
+    }
+  }
+
+  info->unicode_props() = props;
+}
+
+static inline void
+_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
+                                    hb_unicode_general_category_t gen_cat)
+{
+  /* Clears top-byte. */
+  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
+}
+
+static inline hb_unicode_general_category_t
+_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
+{
+  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
+{
+  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+static inline void
+_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
+                                            unsigned int modified_class)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
+    return;
+  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
+}
+static inline unsigned int
+_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
+}
+#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
+
+static inline bool
+_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+        HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
+}
+static inline void
+_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
+    return;
+  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
+}
+static inline hb_unicode_funcs_t::space_t
+_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_space (info) ?
+        (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
+        hb_unicode_funcs_t::NOT_SPACE;
+}
+
+static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
+
+static inline bool
+_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
+{
+  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
+        !_hb_glyph_info_ligated (info);
+}
+static inline bool
+_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
+{
+  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
+         == UPROPS_MASK_IGNORABLE) &&
+        !_hb_glyph_info_ligated (info);
+}
+static inline void
+_hb_glyph_info_unhide (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
+}
+
+static inline void
+_hb_glyph_info_set_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() |= UPROPS_MASK_CONTINUATION;
+}
+static inline void
+_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
+}
+static inline bool
+_hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
+{
+  return info->unicode_props() & UPROPS_MASK_CONTINUATION;
+}
+/* Loop over grapheme. Based on foreach_cluster(). */
+#define foreach_grapheme(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_grapheme (buffer, start))
+
+static inline unsigned int
+_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
+    ;
+
+  return start;
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+        HB_UNICODE_GENERAL_CATEGORY_FORMAT;
+}
+static inline bool
+_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
+}
+static inline bool
+_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
+}
+static inline bool
+_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
+}
+static inline void
+_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
+{
+  if (!_hb_glyph_info_is_unicode_format (info))
+    return;
+  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
+}
+
+/* lig_props: aka lig_id / lig_comp
+ *
+ * When a ligature is formed:
+ *
+ *   - The ligature glyph and any marks in between all the same newly allocated
+ *     lig_id,
+ *   - The ligature glyph will get lig_num_comps set to the number of components
+ *   - The marks get lig_comp > 0, reflecting which component of the ligature
+ *     they were applied to.
+ *   - This is used in GPOS to attach marks to the right component of a ligature
+ *     in MarkLigPos,
+ *   - Note that when marks are ligated together, much of the above is skipped
+ *     and the current lig_id reused.
+ *
+ * When a multiple-substitution is done:
+ *
+ *   - All resulting glyphs will have lig_id = 0,
+ *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
+ *   - This is used in GPOS to attach marks to the first component of a
+ *     multiple substitution in MarkBasePos.
+ *
+ * The numbers are also used in GPOS to do mark-to-mark positioning only
+ * to marks that belong to the same component of the same ligature.
+ */
+
+static inline void
+_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
+{
+  info->lig_props() = 0;
+}
+
+#define IS_LIG_BASE 0x10
+
+static inline void
+_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
+                                          unsigned int lig_id,
+                                          unsigned int lig_num_comps)
+{
+  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
+                                      unsigned int lig_id,
+                                      unsigned int lig_comp)
+{
+  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
+{
+  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
+{
+  return info->lig_props() >> 5;
+}
+
+static inline bool
+_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
+{
+  return !!(info->lig_props() & IS_LIG_BASE);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
+{
+  if (_hb_glyph_info_ligated_internal (info))
+    return 0;
+  else
+    return info->lig_props() & 0x0F;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
+{
+  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
+      _hb_glyph_info_ligated_internal (info))
+    return info->lig_props() & 0x0F;
+  else
+    return 1;
+}
+
+static inline uint8_t
+_hb_allocate_lig_id (hb_buffer_t *buffer) {
+  uint8_t lig_id = buffer->next_serial () & 0x07;
+  if (unlikely (!lig_id))
+    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
+  return lig_id;
+}
+
+/* glyph_props: */
+
+static inline void
+_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
+{
+  info->glyph_props() = props;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
+{
+  return info->glyph_props();
+}
+
+static inline bool
+_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+}
+
+static inline bool
+_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
+}
+
+static inline bool
+_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
+}
+
+static inline bool
+_hb_glyph_info_substituted (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+static inline bool
+_hb_glyph_info_ligated (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
+}
+
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
+static inline void
+_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline void
+_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+
+/* Allocation / deallocation. */
+
+static inline void
+_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+}
+
+static inline void
+_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
+}
+
+static inline void
+_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
+  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
+  HB_BUFFER_ASSERT_VAR (buffer, syllable);
+}
+
+/* Make sure no one directly touches our props... */
+#undef unicode_props0
+#undef unicode_props1
+#undef lig_props
+#undef glyph_props
+
+#endif /* HB_OT_LAYOUT_HH */
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
deleted file mode 100644 (file)
index 4aaf328..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2012,2013  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
- */
-
-#ifndef HB_OT_MAP_PRIVATE_HH
-#define HB_OT_MAP_PRIVATE_HH
-
-#include "hb-buffer-private.hh"
-
-
-struct hb_ot_shape_plan_t;
-
-static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-
-struct hb_ot_map_t
-{
-  friend struct hb_ot_map_builder_t;
-
-  public:
-
-  struct feature_map_t {
-    hb_tag_t tag; /* should be first for our bsearch to work */
-    unsigned int index[2]; /* GSUB/GPOS */
-    unsigned int stage[2]; /* GSUB/GPOS */
-    unsigned int shift;
-    hb_mask_t mask;
-    hb_mask_t _1_mask; /* mask for value=1, for quick access */
-    unsigned int needs_fallback : 1;
-    unsigned int auto_zwnj : 1;
-    unsigned int auto_zwj : 1;
-
-    inline int cmp (const hb_tag_t *tag_) const
-    { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
-  };
-
-  struct lookup_map_t {
-    unsigned short index;
-    unsigned short auto_zwnj : 1;
-    unsigned short auto_zwj : 1;
-    hb_mask_t mask;
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const lookup_map_t *a = (const lookup_map_t *) pa;
-      const lookup_map_t *b = (const lookup_map_t *) pb;
-      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
-    }
-  };
-
-  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
-
-  struct stage_map_t {
-    unsigned int last_lookup; /* Cumulative */
-    pause_func_t pause_func;
-  };
-
-  inline void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-
-    features.init ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].init ();
-      stages[table_index].init ();
-    }
-  }
-  inline void fini (void)
-  {
-    features.fini ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].fini ();
-      stages[table_index].fini ();
-    }
-  }
-
-  inline hb_mask_t get_global_mask (void) const { return global_mask; }
-
-  inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    if (shift) *shift = map ? map->shift : 0;
-    return map ? map->mask : 0;
-  }
-
-  inline bool needs_fallback (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->needs_fallback : false;
-  }
-
-  inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->_1_mask : 0;
-  }
-
-  inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  }
-
-  inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->stage[table_index] : (unsigned int) -1;
-  }
-
-  inline void get_stage_lookups (unsigned int table_index, unsigned int stage,
-                                const struct lookup_map_t **plookups, unsigned int *lookup_count) const {
-    if (unlikely (stage == (unsigned int) -1)) {
-      *plookups = nullptr;
-      *lookup_count = 0;
-      return;
-    }
-    assert (stage <= stages[table_index].len);
-    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
-    unsigned int end   = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len;
-    *plookups = end == start ? nullptr : &lookups[table_index][start];
-    *lookup_count = end - start;
-  }
-
-  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
-  template <typename Proxy>
-  HB_INTERNAL inline void apply (const Proxy &proxy,
-                                const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-
-  public:
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-
-  private:
-
-  hb_mask_t global_mask;
-
-  hb_vector_t<feature_map_t, 8> features;
-  hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
-  hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
-};
-
-enum hb_ot_map_feature_flags_t {
-  F_NONE               = 0x0000u,
-  F_GLOBAL             = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
-  F_HAS_FALLBACK       = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
-  F_MANUAL_ZWNJ                = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
-  F_MANUAL_ZWJ         = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
-  F_GLOBAL_SEARCH      = 0x0010u  /* If feature not found in LangSys, look for it in global feature list and pick one. */
-};
-HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
-/* Macro version for where const is desired. */
-#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-
-
-struct hb_ot_map_builder_t
-{
-  public:
-
-  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
-                                  const hb_segment_properties_t *props_);
-
-  HB_INTERNAL ~hb_ot_map_builder_t (void);
-
-  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
-                               hb_ot_map_feature_flags_t flags);
-
-  inline void add_global_bool_feature (hb_tag_t tag)
-  { add_feature (tag, 1, F_GLOBAL); }
-
-  inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (0, pause_func); }
-  inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (1, pause_func); }
-
-  HB_INTERNAL void compile (hb_ot_map_t  &m,
-                           const int    *coords,
-                           unsigned int  num_coords);
-
-  private:
-
-  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
-                               unsigned int  table_index,
-                               unsigned int  feature_index,
-                               unsigned int  variations_index,
-                               hb_mask_t     mask,
-                               bool          auto_zwnj = true,
-                               bool          auto_zwj = true);
-
-  struct feature_info_t {
-    hb_tag_t tag;
-    unsigned int seq; /* sequence#, used for stable sorting only */
-    unsigned int max_value;
-    hb_ot_map_feature_flags_t flags;
-    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
-    unsigned int stage[2]; /* GSUB/GPOS */
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const feature_info_t *a = (const feature_info_t *) pa;
-      const feature_info_t *b = (const feature_info_t *) pb;
-      return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
-            (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-    }
-  };
-
-  struct stage_info_t {
-    unsigned int index;
-    hb_ot_map_t::pause_func_t pause_func;
-  };
-
-  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
-
-  public:
-
-  hb_face_t *face;
-  hb_segment_properties_t props;
-
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-  unsigned int script_index[2], language_index[2];
-
-  private:
-
-  unsigned int current_stage[2]; /* GSUB/GPOS */
-  hb_vector_t<feature_info_t, 32> feature_infos;
-  hb_vector_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
-};
-
-
-
-#endif /* HB_OT_MAP_PRIVATE_HH */
index 46bf2db..ef0bcc7 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-map-private.hh"
-
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-layout.hh"
 
 
 void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
-  for (unsigned int i = 0; i < lookups[table_index].len; i++)
+  for (unsigned int i = 0; i < lookups[table_index].length; i++)
     hb_set_add (lookups_out, lookups[table_index][i].index);
 }
 
@@ -54,33 +54,35 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
   /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
    * features not available in either table and not waste precious bits for them. */
 
-  hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE};
-  hb_tag_t language_tag;
+  unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+  unsigned int language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
+  hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+  hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
 
-  hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]);
-  language_tag = hb_ot_tag_from_language (props.language);
+  hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
-    found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
-    hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+    found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]);
+    hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]);
   }
 }
 
-hb_ot_map_builder_t::~hb_ot_map_builder_t (void)
+hb_ot_map_builder_t::~hb_ot_map_builder_t ()
 {
   feature_infos.fini ();
   for (unsigned int table_index = 0; table_index < 2; table_index++)
     stages[table_index].fini ();
 }
 
-void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
-                                      hb_ot_map_feature_flags_t flags)
+void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
+                                      hb_ot_map_feature_flags_t flags,
+                                      unsigned int value)
 {
-  feature_info_t *info = feature_infos.push();
   if (unlikely (!tag)) return;
+  feature_info_t *info = feature_infos.push();
   info->tag = tag;
-  info->seq = feature_infos.len;
+  info->seq = feature_infos.length;
   info->max_value = value;
   info->flags = flags;
   info->default_value = (flags & F_GLOBAL) ? value : 0;
@@ -95,7 +97,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t  &m,
                                  unsigned int  variations_index,
                                  hb_mask_t     mask,
                                  bool          auto_zwnj,
-                                 bool          auto_zwj)
+                                 bool          auto_zwj,
+                                 bool          random)
 {
   unsigned int lookup_indices[32];
   unsigned int offset, len;
@@ -122,6 +125,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t  &m,
       lookup->index = lookup_indices[i];
       lookup->auto_zwnj = auto_zwnj;
       lookup->auto_zwj = auto_zwj;
+      lookup->random = random;
     }
 
     offset += len;
@@ -139,13 +143,12 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus
 }
 
 void
-hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
-                             const int    *coords,
-                             unsigned int  num_coords)
+hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
+                             const hb_ot_shape_plan_key_t &key)
 {
   static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
   unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
-  unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
+  unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED);
 
   m.global_mask = global_bit_mask;
 
@@ -171,10 +174,11 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
   }
 
   /* Sort features and merge duplicates */
+  if (feature_infos.length)
   {
     feature_infos.qsort ();
     unsigned int j = 0;
-    for (unsigned int i = 1; i < feature_infos.len; i++)
+    for (unsigned int i = 1; i < feature_infos.length; i++)
       if (feature_infos[i].tag != feature_infos[j].tag)
        feature_infos[++j] = feature_infos[i];
       else {
@@ -198,7 +202,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
   /* Allocate bits now */
   unsigned int next_bit = global_bit_shift + 1;
 
-  for (unsigned int i = 0; i < feature_infos.len; i++)
+  for (unsigned int i = 0; i < feature_infos.length; i++)
   {
     const feature_info_t *info = &feature_infos[i];
 
@@ -208,8 +212,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
       /* Uses the global bit */
       bits_needed = 0;
     else
-      /* Limit to 8 bits per feature. */
-      bits_needed = MIN(8u, _hb_bit_storage (info->max_value));
+      /* Limit bits per feature. */
+      bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
 
     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
@@ -252,6 +256,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
     map->stage[1] = info->stage[1];
     map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
     map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
+    map->random = !!(info->flags & F_RANDOM);
     if ((info->flags & F_GLOBAL) && info->max_value == 1) {
       /* Uses the global bit */
       map->shift = global_bit_shift;
@@ -276,13 +281,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
   {
     /* Collect lookup indices for features */
 
-    unsigned int variations_index;
-    hb_ot_layout_table_find_feature_variations (face,
-                                               table_tags[table_index],
-                                               coords,
-                                               num_coords,
-                                               &variations_index);
-
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
     for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
@@ -291,25 +289,26 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
          required_feature_stage[table_index] == stage)
        add_lookups (m, table_index,
                     required_feature_index[table_index],
-                    variations_index,
+                    key.variations_index[table_index],
                     global_bit_mask);
 
-      for (unsigned i = 0; i < m.features.len; i++)
+      for (unsigned i = 0; i < m.features.length; i++)
         if (m.features[i].stage[table_index] == stage)
          add_lookups (m, table_index,
                       m.features[i].index[table_index],
-                      variations_index,
+                      key.variations_index[table_index],
                       m.features[i].mask,
                       m.features[i].auto_zwnj,
-                      m.features[i].auto_zwj);
+                      m.features[i].auto_zwj,
+                      m.features[i].random);
 
       /* Sort lookups and merge duplicates */
-      if (last_num_lookups < m.lookups[table_index].len)
+      if (last_num_lookups < m.lookups[table_index].length)
       {
-       m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
+       m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
 
        unsigned int j = last_num_lookups;
-       for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
+       for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
          if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
            m.lookups[table_index][++j] = m.lookups[table_index][i];
          else
@@ -321,9 +320,9 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
        m.lookups[table_index].shrink (j + 1);
       }
 
-      last_num_lookups = m.lookups[table_index].len;
+      last_num_lookups = m.lookups[table_index].length;
 
-      if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) {
+      if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
        hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
        stage_map->last_lookup = last_num_lookups;
        stage_map->pause_func = stages[table_index][stage_index].pause_func;
diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh
new file mode 100644 (file)
index 0000000..28407c2
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2012,2013  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
+ */
+
+#ifndef HB_OT_MAP_HH
+#define HB_OT_MAP_HH
+
+#include "hb-buffer.hh"
+
+
+#define HB_OT_MAP_MAX_BITS 8u
+#define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u)
+
+struct hb_ot_shape_plan_t;
+
+static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
+
+struct hb_ot_map_t
+{
+  friend struct hb_ot_map_builder_t;
+
+  public:
+
+  struct feature_map_t {
+    hb_tag_t tag; /* should be first for our bsearch to work */
+    unsigned int index[2]; /* GSUB/GPOS */
+    unsigned int stage[2]; /* GSUB/GPOS */
+    unsigned int shift;
+    hb_mask_t mask;
+    hb_mask_t _1_mask; /* mask for value=1, for quick access */
+    unsigned int needs_fallback : 1;
+    unsigned int auto_zwnj : 1;
+    unsigned int auto_zwj : 1;
+    unsigned int random : 1;
+
+    int cmp (const hb_tag_t tag_) const
+    { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
+  };
+
+  struct lookup_map_t {
+    unsigned short index;
+    unsigned short auto_zwnj : 1;
+    unsigned short auto_zwj : 1;
+    unsigned short random : 1;
+    hb_mask_t mask;
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const lookup_map_t *a = (const lookup_map_t *) pa;
+      const lookup_map_t *b = (const lookup_map_t *) pb;
+      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
+    }
+  };
+
+  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+
+  struct stage_map_t {
+    unsigned int last_lookup; /* Cumulative */
+    pause_func_t pause_func;
+  };
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+
+    features.init ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].init ();
+      stages[table_index].init ();
+    }
+  }
+  void fini ()
+  {
+    features.fini ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].fini ();
+      stages[table_index].fini ();
+    }
+  }
+
+  hb_mask_t get_global_mask () const { return global_mask; }
+
+  hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    if (shift) *shift = map ? map->shift : 0;
+    return map ? map->mask : 0;
+  }
+
+  bool needs_fallback (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->needs_fallback : false;
+  }
+
+  hb_mask_t get_1_mask (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->_1_mask : 0;
+  }
+
+  unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  }
+
+  unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->stage[table_index] : (unsigned int) -1;
+  }
+
+  void get_stage_lookups (unsigned int table_index, unsigned int stage,
+                         const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+  {
+    if (unlikely (stage == (unsigned int) -1)) {
+      *plookups = nullptr;
+      *lookup_count = 0;
+      return;
+    }
+    assert (stage <= stages[table_index].length);
+    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
+    unsigned int end   = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
+    *plookups = end == start ? nullptr : &lookups[table_index][start];
+    *lookup_count = end - start;
+  }
+
+  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
+  template <typename Proxy>
+  HB_INTERNAL inline void apply (const Proxy &proxy,
+                                const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+
+  public:
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+
+  private:
+
+  hb_mask_t global_mask;
+
+  hb_vector_t<feature_map_t> features;
+  hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
+  hb_vector_t<stage_map_t> stages[2]; /* GSUB/GPOS */
+};
+
+enum hb_ot_map_feature_flags_t
+{
+  F_NONE               = 0x0000u,
+  F_GLOBAL             = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
+  F_HAS_FALLBACK       = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
+  F_MANUAL_ZWNJ                = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
+  F_MANUAL_ZWJ         = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
+  F_MANUAL_JOINERS     = F_MANUAL_ZWNJ | F_MANUAL_ZWJ,
+  F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
+  F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
+  F_GLOBAL_SEARCH      = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
+  F_RANDOM             = 0x0020u  /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+};
+HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
+
+
+struct hb_ot_map_feature_t
+{
+  hb_tag_t tag;
+  hb_ot_map_feature_flags_t flags;
+};
+
+struct hb_ot_shape_plan_key_t;
+
+struct hb_ot_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
+                                  const hb_segment_properties_t *props_);
+
+  HB_INTERNAL ~hb_ot_map_builder_t ();
+
+  HB_INTERNAL void add_feature (hb_tag_t tag,
+                               hb_ot_map_feature_flags_t flags=F_NONE,
+                               unsigned int value=1);
+
+  void add_feature (const hb_ot_map_feature_t &feat)
+  { add_feature (feat.tag, feat.flags); }
+
+  void enable_feature (hb_tag_t tag,
+                             hb_ot_map_feature_flags_t flags=F_NONE,
+                             unsigned int value=1)
+  { add_feature (tag, F_GLOBAL | flags, value); }
+
+  void disable_feature (hb_tag_t tag)
+  { add_feature (tag, F_GLOBAL, 0); }
+
+  void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (0, pause_func); }
+  void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (1, pause_func); }
+
+  HB_INTERNAL void compile (hb_ot_map_t                  &m,
+                           const hb_ot_shape_plan_key_t &key);
+
+  private:
+
+  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
+                               unsigned int  table_index,
+                               unsigned int  feature_index,
+                               unsigned int  variations_index,
+                               hb_mask_t     mask,
+                               bool          auto_zwnj = true,
+                               bool          auto_zwj = true,
+                               bool          random = false);
+
+  struct feature_info_t {
+    hb_tag_t tag;
+    unsigned int seq; /* sequence#, used for stable sorting only */
+    unsigned int max_value;
+    hb_ot_map_feature_flags_t flags;
+    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
+    unsigned int stage[2]; /* GSUB/GPOS */
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const feature_info_t *a = (const feature_info_t *) pa;
+      const feature_info_t *b = (const feature_info_t *) pb;
+      return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
+            (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+  };
+
+  struct stage_info_t {
+    unsigned int index;
+    hb_ot_map_t::pause_func_t pause_func;
+  };
+
+  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
+
+  public:
+
+  hb_face_t *face;
+  hb_segment_properties_t props;
+
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+  unsigned int script_index[2], language_index[2];
+
+  private:
+
+  unsigned int current_stage[2]; /* GSUB/GPOS */
+  hb_vector_t<feature_info_t> feature_infos;
+  hb_vector_t<stage_info_t> stages[2]; /* GSUB/GPOS */
+};
+
+
+
+#endif /* HB_OT_MAP_HH */
index 5fef2d2..62bf072 100644 (file)
@@ -27,8 +27,8 @@
 #ifndef HB_OT_MATH_TABLE_HH
 #define HB_OT_MATH_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
 #include "hb-ot-math.h"
 
 namespace OT {
@@ -36,12 +36,12 @@ namespace OT {
 
 struct MathValueRecord
 {
-  inline hb_position_t get_x_value (hb_font_t *font, const void *base) const
+  hb_position_t get_x_value (hb_font_t *font, const void *base) const
   { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
-  inline hb_position_t get_y_value (hb_font_t *font, const void *base) const
+  hb_position_t get_y_value (hb_font_t *font, const void *base) const
   { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
@@ -50,7 +50,7 @@ struct MathValueRecord
   protected:
   HBINT16                      value;          /* The X or Y value in design units */
   OffsetTo<Device>     deviceTable;    /* Offset to the device table - from the
-                                        * beginning of parent table. May be nullptr.
+                                        * beginning of parent table.  May be NULL.
                                         * Suggested format for device table is 1. */
 
   public:
@@ -59,7 +59,7 @@ struct MathValueRecord
 
 struct MathConstants
 {
-  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
@@ -71,13 +71,13 @@ struct MathConstants
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && sanitize_math_value_records(c));
+    return_trace (c->check_struct (this) && sanitize_math_value_records (c));
   }
 
-  inline hb_position_t get_value (hb_ot_math_constant_t constant,
+  hb_position_t get_value (hb_ot_math_constant_t constant,
                                  hb_font_t *font) const
   {
     switch (constant) {
@@ -94,7 +94,7 @@ struct MathConstants
     case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
     case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
     case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this);
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value (font, this);
 
     case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
     case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
@@ -143,7 +143,7 @@ struct MathConstants
     case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
     case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
     case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
-      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this);
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value (font, this);
 
     case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
       return radicalDegreeBottomRaisePercent;
@@ -165,7 +165,7 @@ struct MathConstants
 
 struct MathItalicsCorrectionInfo
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -173,8 +173,8 @@ struct MathItalicsCorrectionInfo
                  italicsCorrection.sanitize (c, this));
   }
 
-  inline hb_position_t get_value (hb_codepoint_t glyph,
-                                 hb_font_t *font) const
+  hb_position_t get_value (hb_codepoint_t glyph,
+                          hb_font_t *font) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph);
     return italicsCorrection[index].get_x_value (font, this);
@@ -196,7 +196,7 @@ struct MathItalicsCorrectionInfo
 
 struct MathTopAccentAttachment
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -204,13 +204,13 @@ struct MathTopAccentAttachment
                  topAccentAttachment.sanitize (c, this));
   }
 
-  inline hb_position_t get_value (hb_codepoint_t glyph,
-                                 hb_font_t *font) const
+  hb_position_t get_value (hb_codepoint_t glyph,
+                          hb_font_t *font) const
   {
     unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
     if (index == NOT_COVERED)
       return font->get_glyph_h_advance (glyph) / 2;
-    return topAccentAttachment[index].get_x_value(font, this);
+    return topAccentAttachment[index].get_x_value (font, this);
   }
 
   protected:
@@ -229,29 +229,27 @@ struct MathTopAccentAttachment
 
 struct MathKern
 {
-  inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     unsigned int count = 2 * heightCount + 1;
     for (unsigned int i = 0; i < count; i++)
-      if (!mathValueRecords[i].sanitize (c, this)) return_trace (false);
+      if (!mathValueRecordsZ.arrayZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 c->check_array (mathValueRecords,
-                                 mathValueRecords[0].static_size,
-                                 2 * heightCount + 1) &&
+                 c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
                  sanitize_math_value_records (c));
   }
 
-  inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
+  hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
   {
-    const MathValueRecord* correctionHeight = mathValueRecords;
-    const MathValueRecord* kernValue = mathValueRecords + heightCount;
+    const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+    const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
     int sign = font->y_scale < 0 ? -1 : +1;
 
     /* The description of the MathKern table is a ambiguous, but interpreting
@@ -267,7 +265,7 @@ struct MathKern
     while (count > 0)
     {
       unsigned int half = count / 2;
-      hb_position_t height = correctionHeight[i + half].get_y_value(font, this);
+      hb_position_t height = correctionHeight[i + half].get_y_value (font, this);
       if (sign * height < sign * correction_height)
       {
        i += half + 1;
@@ -275,27 +273,28 @@ struct MathKern
       } else
        count = half;
     }
-    return kernValue[i].get_x_value(font, this);
+    return kernValue[i].get_x_value (font, this);
   }
 
   protected:
-  HBUINT16       heightCount;
-  MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at
-                                         * which the kern value changes.
-                                         * Sorted by the height value in
-                                         * design units (heightCount entries),
-                                         * Followed by:
-                                         * Array of kern values corresponding
-                                         * to heights. (heightCount+1 entries).
-                                         */
+  HBUINT16     heightCount;
+  UnsizedArrayOf<MathValueRecord>
+               mathValueRecordsZ;      /* Array of correction heights at
+                                        * which the kern value changes.
+                                        * Sorted by the height value in
+                                        * design units (heightCount entries),
+                                        * Followed by:
+                                        * Array of kern values corresponding
+                                        * to heights. (heightCount+1 entries).
+                                        */
 
   public:
-  DEFINE_SIZE_ARRAY (2, mathValueRecords);
+  DEFINE_SIZE_ARRAY (2, mathValueRecordsZ);
 };
 
 struct MathKernInfoRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
 
@@ -307,10 +306,10 @@ struct MathKernInfoRecord
     return_trace (true);
   }
 
-  inline hb_position_t get_kerning (hb_ot_math_kern_t kern,
-                                   hb_position_t correction_height,
-                                   hb_font_t *font,
-                                   const void *base) const
+  hb_position_t get_kerning (hb_ot_math_kern_t kern,
+                            hb_position_t correction_height,
+                            hb_font_t *font,
+                            const void *base) const
   {
     unsigned int idx = kern;
     if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
@@ -319,7 +318,7 @@ struct MathKernInfoRecord
 
   protected:
   /* Offset to MathKern table for each corner -
-   * from the beginning of MathKernInfo table. May be nullptr. */
+   * from the beginning of MathKernInfo table.  May be NULL. */
   OffsetTo<MathKern> mathKern[4];
 
   public:
@@ -328,7 +327,7 @@ struct MathKernInfoRecord
 
 struct MathKernInfo
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -336,10 +335,10 @@ struct MathKernInfo
                  mathKernInfoRecords.sanitize (c, this));
   }
 
-  inline hb_position_t get_kerning (hb_codepoint_t glyph,
-                                   hb_ot_math_kern_t kern,
-                                   hb_position_t correction_height,
-                                   hb_font_t *font) const
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                            hb_ot_math_kern_t kern,
+                            hb_position_t correction_height,
+                            hb_font_t *font) const
   {
     unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
     return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
@@ -362,31 +361,31 @@ struct MathKernInfo
 
 struct MathGlyphInfo
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                  mathItalicsCorrectionInfo.sanitize (c, this) &&
                  mathTopAccentAttachment.sanitize (c, this) &&
                  extendedShapeCoverage.sanitize (c, this) &&
-                 mathKernInfo.sanitize(c, this));
+                 mathKernInfo.sanitize (c, this));
   }
 
-  inline hb_position_t
+  hb_position_t
   get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
   { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
 
-  inline hb_position_t
+  hb_position_t
   get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
   { return (this+mathTopAccentAttachment).get_value (glyph, font); }
 
-  inline bool is_extended_shape (hb_codepoint_t glyph) const
+  bool is_extended_shape (hb_codepoint_t glyph) const
   { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
 
-  inline hb_position_t get_kerning (hb_codepoint_t glyph,
-                                   hb_ot_math_kern_t kern,
-                                   hb_position_t correction_height,
-                                   hb_font_t *font) const
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                            hb_ot_math_kern_t kern,
+                            hb_position_t correction_height,
+                            hb_font_t *font) const
   { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
 
   protected:
@@ -402,7 +401,7 @@ struct MathGlyphInfo
    * from the beginning of MathGlyphInfo table. When the left or right glyph of
    * a box is an extended shape variant, the (ink) box (and not the default
    * position defined by values in MathConstants table) should be used for
-   * vertical positioning purposes. May be nullptr.. */
+   * vertical positioning purposes.  May be NULL.. */
   OffsetTo<Coverage> extendedShapeCoverage;
 
    /* Offset to MathKernInfo table -
@@ -417,7 +416,7 @@ struct MathGlyphVariantRecord
 {
   friend struct MathGlyphConstruction;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -426,8 +425,8 @@ struct MathGlyphVariantRecord
   protected:
   GlyphID variantGlyph;       /* Glyph ID for the variant. */
   HBUINT16  advanceMeasurement; /* Advance width/height, in design units, of the
-                              * variant, in the direction of requested
-                              * glyph extension. */
+                                * variant, in the direction of requested
+                                * glyph extension. */
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -447,15 +446,15 @@ struct PartFlags : HBUINT16
 
 struct MathGlyphPartRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline void extract (hb_ot_math_glyph_part_t &out,
-                      int scale,
-                      hb_font_t *font) const
+  void extract (hb_ot_math_glyph_part_t &out,
+               int scale,
+               hb_font_t *font) const
   {
     out.glyph                  = glyph;
 
@@ -492,27 +491,26 @@ struct MathGlyphPartRecord
 
 struct MathGlyphAssembly
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 italicsCorrection.sanitize(c, this) &&
-                 partRecords.sanitize(c));
+                 italicsCorrection.sanitize (c, this) &&
+                 partRecords.sanitize (c));
   }
 
-  inline unsigned int get_parts (hb_direction_t direction,
-                                hb_font_t *font,
-                                unsigned int start_offset,
-                                unsigned int *parts_count, /* IN/OUT */
-                                hb_ot_math_glyph_part_t *parts /* OUT */,
-                                hb_position_t *italics_correction /* OUT */) const
+  unsigned int get_parts (hb_direction_t direction,
+                         hb_font_t *font,
+                         unsigned int start_offset,
+                         unsigned int *parts_count, /* IN/OUT */
+                         hb_ot_math_glyph_part_t *parts /* OUT */,
+                         hb_position_t *italics_correction /* OUT */) const
   {
     if (parts_count)
     {
       int scale = font->dir_scale (direction);
-      const MathGlyphPartRecord *arr =
-           partRecords.sub_array (start_offset, parts_count);
-      unsigned int count = *parts_count;
+      hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
+      unsigned int count = arr.length;
       for (unsigned int i = 0; i < count; i++)
        arr[i].extract (parts[i], scale, font);
     }
@@ -537,29 +535,27 @@ struct MathGlyphAssembly
 
 struct MathGlyphConstruction
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 glyphAssembly.sanitize(c, this) &&
-                 mathGlyphVariantRecord.sanitize(c));
+                 glyphAssembly.sanitize (c, this) &&
+                 mathGlyphVariantRecord.sanitize (c));
   }
 
-  inline const MathGlyphAssembly &get_assembly (void) const
-  { return this+glyphAssembly; }
+  const MathGlyphAssembly &get_assembly () const { return this+glyphAssembly; }
 
-  inline unsigned int get_variants (hb_direction_t direction,
-                                   hb_font_t *font,
-                                   unsigned int start_offset,
-                                   unsigned int *variants_count, /* IN/OUT */
-                                   hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  unsigned int get_variants (hb_direction_t direction,
+                            hb_font_t *font,
+                            unsigned int start_offset,
+                            unsigned int *variants_count, /* IN/OUT */
+                            hb_ot_math_glyph_variant_t *variants /* OUT */) const
   {
     if (variants_count)
     {
       int scale = font->dir_scale (direction);
-      const MathGlyphVariantRecord *arr =
-           mathGlyphVariantRecord.sub_array (start_offset, variants_count);
-      unsigned int count = *variants_count;
+      hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+      unsigned int count = arr.length;
       for (unsigned int i = 0; i < count; i++)
       {
        variants[i].glyph = arr[i].variantGlyph;
@@ -571,7 +567,7 @@ struct MathGlyphConstruction
 
   protected:
   /* Offset to MathGlyphAssembly table for this shape - from the beginning of
-     MathGlyphConstruction table. May be nullptr. */
+     MathGlyphConstruction table.  May be NULL. */
   OffsetTo<MathGlyphAssembly>    glyphAssembly;
 
   /* MathGlyphVariantRecords for alternative variants of the glyphs. */
@@ -583,41 +579,39 @@ struct MathGlyphConstruction
 
 struct MathVariants
 {
-  inline bool sanitize_offsets (hb_sanitize_context_t *c) const
+  bool sanitize_offsets (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     unsigned int count = vertGlyphCount + horizGlyphCount;
     for (unsigned int i = 0; i < count; i++)
-      if (!glyphConstruction[i].sanitize (c, this)) return_trace (false);
+      if (!glyphConstruction.arrayZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                  vertGlyphCoverage.sanitize (c, this) &&
                  horizGlyphCoverage.sanitize (c, this) &&
-                 c->check_array (glyphConstruction,
-                                 glyphConstruction[0].static_size,
-                                 vertGlyphCount + horizGlyphCount) &&
+                 c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
                  sanitize_offsets (c));
   }
 
-  inline hb_position_t get_min_connector_overlap (hb_direction_t direction,
+  hb_position_t get_min_connector_overlap (hb_direction_t direction,
                                                  hb_font_t *font) const
   { return font->em_scale_dir (minConnectorOverlap, direction); }
 
-  inline unsigned int get_glyph_variants (hb_codepoint_t glyph,
-                                         hb_direction_t direction,
-                                         hb_font_t *font,
-                                         unsigned int start_offset,
-                                         unsigned int *variants_count, /* IN/OUT */
-                                         hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  unsigned int get_glyph_variants (hb_codepoint_t glyph,
+                                  hb_direction_t direction,
+                                  hb_font_t *font,
+                                  unsigned int start_offset,
+                                  unsigned int *variants_count, /* IN/OUT */
+                                  hb_ot_math_glyph_variant_t *variants /* OUT */) const
   { return get_glyph_construction (glyph, direction, font)
           .get_variants (direction, font, start_offset, variants_count, variants); }
 
-  inline unsigned int get_glyph_parts (hb_codepoint_t glyph,
+  unsigned int get_glyph_parts (hb_codepoint_t glyph,
                                       hb_direction_t direction,
                                       hb_font_t *font,
                                       unsigned int start_offset,
@@ -631,10 +625,10 @@ struct MathVariants
                       italics_correction); }
 
   private:
-  inline const MathGlyphConstruction &
-               get_glyph_construction (hb_codepoint_t glyph,
-                                       hb_direction_t direction,
-                                       hb_font_t *font) const
+  const MathGlyphConstruction &
+  get_glyph_construction (hb_codepoint_t glyph,
+                         hb_direction_t direction,
+                         hb_font_t *font HB_UNUSED) const
   {
     bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
@@ -642,7 +636,7 @@ struct MathVariants
                                                  : horizGlyphCoverage;
 
     unsigned int index = (this+coverage).get_coverage (glyph);
-    if (unlikely (index >= count)) return Null(MathGlyphConstruction);
+    if (unlikely (index >= count)) return Null (MathGlyphConstruction);
 
     if (!vertical)
       index += vertGlyphCount;
@@ -670,7 +664,8 @@ struct MathVariants
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
-  OffsetTo<MathGlyphConstruction> glyphConstruction[VAR];
+  UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
+                       glyphConstruction;
 
   public:
   DEFINE_SIZE_ARRAY (10, glyphConstruction);
@@ -684,9 +679,11 @@ struct MathVariants
 
 struct MATH
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_MATH;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MATH;
+
+  bool has_data () const { return version.to_int (); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -696,15 +693,13 @@ struct MATH
                  mathVariants.sanitize (c, this));
   }
 
-  inline hb_position_t get_constant (hb_ot_math_constant_t  constant,
+  hb_position_t get_constant (hb_ot_math_constant_t  constant,
                                     hb_font_t             *font) const
   { return (this+mathConstants).get_value (constant, font); }
 
-  inline const MathGlyphInfo &get_math_glyph_info (void) const
-  { return this+mathGlyphInfo; }
+  const MathGlyphInfo &get_glyph_info () const { return this+mathGlyphInfo; }
 
-  inline const MathVariants &get_math_variants (void) const
-  { return this+mathVariants; }
+  const MathVariants &get_variants () const    { return this+mathVariants; }
 
   protected:
   FixedVersion<>version;               /* Version of the MATH table
index 1667a7d..bd31bf5 100644 (file)
  * Igalia Author(s): Frédéric Wang
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-face.hh"
 #include "hb-ot-math-table.hh"
 
-static inline const OT::MATH&
-_get_math (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::MATH);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->math.get ());
-}
+
+/**
+ * SECTION:hb-ot-math
+ * @title: hb-ot-math
+ * @short_description: OpenType Math information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching mathematics layout data from OpenType fonts.
+ **/
+
 
 /*
  * OT::MATH
@@ -55,7 +58,7 @@ _get_math (hb_face_t *face)
 hb_bool_t
 hb_ot_math_has_data (hb_face_t *face)
 {
-  return &_get_math (face) != &Null(OT::MATH);
+  return face->table.MATH->has_data ();
 }
 
 /**
@@ -77,8 +80,7 @@ hb_position_t
 hb_ot_math_get_constant (hb_font_t *font,
                         hb_ot_math_constant_t constant)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_constant(constant, font);
+  return font->face->table.MATH->get_constant(constant, font);
 }
 
 /**
@@ -94,8 +96,7 @@ hb_position_t
 hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
                                         hb_codepoint_t glyph)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_italics_correction (glyph, font);
+  return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
 }
 
 /**
@@ -111,8 +112,7 @@ hb_position_t
 hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
                                            hb_codepoint_t glyph)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_top_accent_attachment (glyph, font);
+  return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
 }
 
 /**
@@ -128,8 +128,7 @@ hb_bool_t
 hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
                                    hb_codepoint_t glyph)
 {
-  const OT::MATH &math = _get_math (face);
-  return math.get_math_glyph_info().is_extended_shape (glyph);
+  return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
 }
 
 /**
@@ -155,8 +154,10 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
                              hb_ot_math_kern_t kern,
                              hb_position_t correction_height)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font);
+  return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
+                                                              kern,
+                                                              correction_height,
+                                                              font);
 }
 
 /**
@@ -186,11 +187,10 @@ hb_ot_math_get_glyph_variants (hb_font_t *font,
                               unsigned int *variants_count, /* IN/OUT */
                               hb_ot_math_glyph_variant_t *variants /* OUT */)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_glyph_variants (glyph, direction, font,
-                                                     start_offset,
-                                                     variants_count,
-                                                     variants);
+  return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
+                                                                   start_offset,
+                                                                   variants_count,
+                                                                   variants);
 }
 
 /**
@@ -211,8 +211,7 @@ hb_position_t
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
                                      hb_direction_t direction)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_min_connector_overlap (direction, font);
+  return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
 }
 
 /**
@@ -244,10 +243,11 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font,
                               hb_ot_math_glyph_part_t *parts, /* OUT */
                               hb_position_t *italics_correction /* OUT */)
 {
-  const OT::MATH &math = _get_math (font->face);
-  return math.get_math_variants().get_glyph_parts (glyph, direction, font,
-                                                  start_offset,
-                                                  parts_count,
-                                                  parts,
-                                                  italics_correction);
+  return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
+                                                                direction,
+                                                                font,
+                                                                start_offset,
+                                                                parts_count,
+                                                                parts,
+                                                                italics_correction);
 }
index 390b60d..e4b67ab 100644 (file)
@@ -27,8 +27,7 @@
 #ifndef HB_OT_MAXP_TABLE_HH
 #define HB_OT_MAXP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 namespace OT {
 
@@ -42,7 +41,7 @@ namespace OT {
 
 struct maxpV1Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -72,19 +71,16 @@ struct maxpV1Tail
 
 struct maxp
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_maxp;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_maxp;
 
-  inline unsigned int get_num_glyphs (void) const
-  {
-    return numGlyphs;
-  }
+  unsigned int get_num_glyphs () const { return numGlyphs; }
 
-  inline void set_num_glyphs (unsigned int count)
+  void set_num_glyphs (unsigned int count)
   {
     numGlyphs.set (count);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -93,23 +89,23 @@ struct maxp
     if (version.major == 1)
     {
       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
-      return v1.sanitize (c);
+      return_trace (v1.sanitize (c));
     }
     return_trace (likely (version.major == 0 && version.minor == 0x5000u));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
-    hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
+    hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
     hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
     hb_blob_destroy (maxp_blob);
 
     if (unlikely (!maxp_prime_blob)) {
       return false;
     }
-    OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
+    maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
 
-    maxp_prime->set_num_glyphs (plan->glyphs.len);
+    maxp_prime->set_num_glyphs (plan->glyphs.length);
     if (plan->drop_hints)
       drop_hint_fields (plan, maxp_prime);
 
@@ -118,7 +114,7 @@ struct maxp
     return result;
   }
 
-  static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
+  static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
   {
     if (maxp_prime->version.major == 1)
     {
@@ -137,7 +133,7 @@ struct maxp
   FixedVersion<>version;               /* Version of the maxp table (0.5 or 1.0),
                                         * 0x00005000u or 0x00010000u. */
   HBUINT16     numGlyphs;              /* The number of glyphs in the font. */
-/*maxpV1Tail v1Tail[VAR]; */
+/*maxpV1Tail   v1Tail[VAR]; */
   public:
   DEFINE_SIZE_STATIC (6);
 };
diff --git a/src/hb-ot-name-language.cc b/src/hb-ot-name-language.cc
new file mode 100644 (file)
index 0000000..0e37e0a
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-name-language.hh"
+
+/* Following two tables were generated by joining FreeType, FontConfig,
+ * and OpenType specification language lists, then filled in missing
+ * entries using:
+ * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings
+ */
+
+struct hb_ot_language_map_t
+{
+  static int cmp (const void *key, const void *item)
+  {
+    unsigned int a = * (unsigned int *) key;
+    unsigned int b = ((const hb_ot_language_map_t *) item)->code;
+    return a < b ? -1 : a > b ? +1 : 0;
+  }
+
+  uint16_t     code;
+  char         lang[6];
+};
+
+static const hb_ot_language_map_t
+hb_ms_language_map[] =
+{
+  {0x0001,     "ar"},  /* ??? */
+  {0x0004,     "zh"},  /* ??? */
+  {0x0009,     "en"},  /* ??? */
+  {0x0401,     "ar"},  /* Arabic (Saudi Arabia) */
+  {0x0402,     "bg"},  /* Bulgarian (Bulgaria) */
+  {0x0403,     "ca"},  /* Catalan (Catalan) */
+  {0x0404,     "zh-tw"},       /* Chinese (Taiwan) */
+  {0x0405,     "cs"},  /* Czech (Czech Republic) */
+  {0x0406,     "da"},  /* Danish (Denmark) */
+  {0x0407,     "de"},  /* German (Germany) */
+  {0x0408,     "el"},  /* Greek (Greece) */
+  {0x0409,     "en"},  /* English (United States) */
+  {0x040A,     "es"},  /* Spanish (Traditional Sort) (Spain) */
+  {0x040B,     "fi"},  /* Finnish (Finland) */
+  {0x040C,     "fr"},  /* French (France) */
+  {0x040D,     "he"},  /* Hebrew (Israel) */
+  {0x040E,     "hu"},  /* Hungarian (Hungary) */
+  {0x040F,     "is"},  /* Icelandic (Iceland) */
+  {0x0410,     "it"},  /* Italian (Italy) */
+  {0x0411,     "ja"},  /* Japanese (Japan) */
+  {0x0412,     "ko"},  /* Korean (Korea) */
+  {0x0413,     "nl"},  /* Dutch (Netherlands) */
+  {0x0414,     "no"},  /* Norwegian (Bokmal) (Norway) */
+  {0x0415,     "pl"},  /* Polish (Poland) */
+  {0x0416,     "pt"},  /* Portuguese (Brazil) */
+  {0x0417,     "rm"},  /* Romansh (Switzerland) */
+  {0x0418,     "ro"},  /* Romanian (Romania) */
+  {0x0419,     "ru"},  /* Russian (Russia) */
+  {0x041A,     "hr"},  /* Croatian (Croatia) */
+  {0x041B,     "sk"},  /* Slovak (Slovakia) */
+  {0x041C,     "sq"},  /* Albanian (Albania) */
+  {0x041D,     "sv"},  /* Swedish (Sweden) */
+  {0x041E,     "th"},  /* Thai (Thailand) */
+  {0x041F,     "tr"},  /* Turkish (Turkey) */
+  {0x0420,     "ur"},  /* Urdu (Islamic Republic of Pakistan) */
+  {0x0421,     "id"},  /* Indonesian (Indonesia) */
+  {0x0422,     "uk"},  /* Ukrainian (Ukraine) */
+  {0x0423,     "be"},  /* Belarusian (Belarus) */
+  {0x0424,     "sl"},  /* Slovenian (Slovenia) */
+  {0x0425,     "et"},  /* Estonian (Estonia) */
+  {0x0426,     "lv"},  /* Latvian (Latvia) */
+  {0x0427,     "lt"},  /* Lithuanian (Lithuania) */
+  {0x0428,     "tg"},  /* Tajik (Cyrillic) (Tajikistan) */
+  {0x0429,     "fa"},  /* Persian (Iran) */
+  {0x042A,     "vi"},  /* Vietnamese (Vietnam) */
+  {0x042B,     "hy"},  /* Armenian (Armenia) */
+  {0x042C,     "az"},  /* Azeri (Latin) (Azerbaijan) */
+  {0x042D,     "eu"},  /* Basque (Basque) */
+  {0x042E,     "hsb"}, /* Upper Sorbian (Germany) */
+  {0x042F,     "mk"},  /* Macedonian (FYROM) (Former Yugoslav Republic of Macedonia) */
+  {0x0430,     "st"},  /* ??? */
+  {0x0431,     "ts"},  /* ??? */
+  {0x0432,     "tn"},  /* Setswana (South Africa) */
+  {0x0433,     "ven"}, /* ??? */
+  {0x0434,     "xh"},  /* isiXhosa (South Africa) */
+  {0x0435,     "zu"},  /* isiZulu (South Africa) */
+  {0x0436,     "af"},  /* Afrikaans (South Africa) */
+  {0x0437,     "ka"},  /* Georgian (Georgia) */
+  {0x0438,     "fo"},  /* Faroese (Faroe Islands) */
+  {0x0439,     "hi"},  /* Hindi (India) */
+  {0x043A,     "mt"},  /* Maltese (Malta) */
+  {0x043B,     "se"},  /* Sami (Northern) (Norway) */
+  {0x043C,     "ga"},  /* ??? */
+  {0x043D,     "yi"},  /* ??? */
+  {0x043E,     "ms"},  /* Malay (Malaysia) */
+  {0x043F,     "kk"},  /* Kazakh (Kazakhstan) */
+  {0x0440,     "ky"},  /* Kyrgyz (Kyrgyzstan) */
+  {0x0441,     "sw"},  /* Kiswahili (Kenya) */
+  {0x0442,     "tk"},  /* Turkmen (Turkmenistan) */
+  {0x0443,     "uz"},  /* Uzbek (Latin) (Uzbekistan) */
+  {0x0444,     "tt"},  /* Tatar (Russia) */
+  {0x0445,     "bn"},  /* Bengali (India) */
+  {0x0446,     "pa"},  /* Punjabi (India) */
+  {0x0447,     "gu"},  /* Gujarati (India) */
+  {0x0448,     "or"},  /* Odia (formerly Oriya) (India) */
+  {0x0449,     "ta"},  /* Tamil (India) */
+  {0x044A,     "te"},  /* Telugu (India) */
+  {0x044B,     "kn"},  /* Kannada (India) */
+  {0x044C,     "ml"},  /* Malayalam (India) */
+  {0x044D,     "as"},  /* Assamese (India) */
+  {0x044E,     "mr"},  /* Marathi (India) */
+  {0x044F,     "sa"},  /* Sanskrit (India) */
+  {0x0450,     "mn"},  /* Mongolian (Cyrillic) (Mongolia) */
+  {0x0451,     "bo"},  /* Tibetan (PRC) */
+  {0x0452,     "cy"},  /* Welsh (United Kingdom) */
+  {0x0453,     "km"},  /* Khmer (Cambodia) */
+  {0x0454,     "lo"},  /* Lao (Lao P.D.R.) */
+  {0x0455,     "my"},  /* ??? */
+  {0x0456,     "gl"},  /* Galician (Galician) */
+  {0x0457,     "kok"}, /* Konkani (India) */
+  {0x0458,     "mni"}, /* ??? */
+  {0x0459,     "sd"},  /* ??? */
+  {0x045A,     "syr"}, /* Syriac (Syria) */
+  {0x045B,     "si"},  /* Sinhala (Sri Lanka) */
+  {0x045C,     "chr"}, /* ??? */
+  {0x045D,     "iu"},  /* Inuktitut (Canada) */
+  {0x045E,     "am"},  /* Amharic (Ethiopia) */
+  {0x0460,     "ks"},  /* ??? */
+  {0x0461,     "ne"},  /* Nepali (Nepal) */
+  {0x0462,     "fy"},  /* Frisian (Netherlands) */
+  {0x0463,     "ps"},  /* Pashto (Afghanistan) */
+  {0x0464,     "phi"}, /* Filipino (Philippines) */
+  {0x0465,     "div"}, /* Divehi (Maldives) */
+  {0x0468,     "ha"},  /* Hausa (Latin) (Nigeria) */
+  {0x046A,     "yo"},  /* Yoruba (Nigeria) */
+  {0x046B,     "quz"}, /* Quechua (Bolivia) */
+  {0x046C,     "nso"}, /* Sesotho sa Leboa (South Africa) */
+  {0x046D,     "ba"},  /* Bashkir (Russia) */
+  {0x046E,     "lb"},  /* Luxembourgish (Luxembourg) */
+  {0x046F,     "kl"},  /* Greenlandic (Greenland) */
+  {0x0470,     "ibo"}, /* Igbo (Nigeria) */
+  {0x0471,     "kau"}, /* ??? */
+  {0x0472,     "om"},  /* ??? */
+  {0x0473,     "ti"},  /* ??? */
+  {0x0474,     "gn"},  /* ??? */
+  {0x0475,     "haw"}, /* ??? */
+  {0x0476,     "la"},  /* ??? */
+  {0x0477,     "so"},  /* ??? */
+  {0x0478,     "ii"},  /* Yi (PRC) */
+  {0x0479,     "pap"}, /* ??? */
+  {0x047A,     "arn"}, /* Mapudungun (Chile) */
+  {0x047C,     "moh"}, /* Mohawk (Mohawk) */
+  {0x047E,     "br"},  /* Breton (France) */
+  {0x0480,     "ug"},  /* Uighur (PRC) */
+  {0x0481,     "mi"},  /* Maori (New Zealand) */
+  {0x0482,     "oc"},  /* Occitan (France) */
+  {0x0483,     "co"},  /* Corsican (France) */
+  {0x0484,     "gsw"}, /* Alsatian (France) */
+  {0x0485,     "sah"}, /* Yakut (Russia) */
+  {0x0486,     "qut"}, /* K'iche (Guatemala) */
+  {0x0487,     "rw"},  /* Kinyarwanda (Rwanda) */
+  {0x0488,     "wo"},  /* Wolof (Senegal) */
+  {0x048C,     "fa"},  /* Dari (Afghanistan) */
+  {0x0801,     "ar"},  /* Arabic (Iraq) */
+  {0x0804,     "zh-cn"},       /* Chinese (People’s Republic of China) */
+  {0x0807,     "de"},  /* German (Switzerland) */
+  {0x0809,     "en"},  /* English (United Kingdom) */
+  {0x080A,     "es"},  /* Spanish (Mexico) */
+  {0x080C,     "fr"},  /* French (Belgium) */
+  {0x0810,     "it"},  /* Italian (Switzerland) */
+  {0x0812,     "ko"},  /* ??? */
+  {0x0813,     "nl"},  /* Dutch (Belgium) */
+  {0x0814,     "nn"},  /* Norwegian (Nynorsk) (Norway) */
+  {0x0816,     "pt"},  /* Portuguese (Portugal) */
+  {0x0818,     "mo"},  /* ??? */
+  {0x0819,     "ru"},  /* ??? */
+  {0x081A,     "sr"},  /* Serbian (Latin) (Serbia) */
+  {0x081D,     "sv"},  /* Sweden (Finland) */
+  {0x0820,     "ur"},  /* ??? */
+  {0x0827,     "lt"},  /* ??? */
+  {0x082C,     "az"},  /* Azeri (Cyrillic) (Azerbaijan) */
+  {0x082E,     "dsb"}, /* Lower Sorbian (Germany) */
+//{0x083B,     ""},    /* Sami (Northern) (Sweden) */
+  {0x083C,     "gd"},  /* Irish (Ireland) */
+  {0x083E,     "ms"},  /* Malay (Brunei Darussalam) */
+  {0x0843,     "uz"},  /* Uzbek (Cyrillic) (Uzbekistan) */
+  {0x0845,     "bn"},  /* Bengali (Bangladesh) */
+  {0x0846,     "ar"},  /* ??? */
+  {0x0850,     "mn"},  /* Mongolian (Traditional) (People’s Republic of China) */
+  {0x0851,     "dz"},  /* ??? */
+  {0x085D,     "iu"},  /* Inuktitut (Latin) (Canada) */
+  {0x085F,     "tzm"}, /* Tamazight (Latin) (Algeria) */
+  {0x0861,     "ne"},  /* ??? */
+//{0x086B,     ""},    /* Quechua (Ecuador) */
+  {0x0873,     "ti"},  /* ??? */
+  {0x0C01,     "ar"},  /* Arabic (Egypt) */
+  {0x0C04,     "zh-hk"},       /* Chinese (Hong Kong S.A.R.) */
+  {0x0C07,     "de"},  /* German (Austria) */
+  {0x0C09,     "en"},  /* English (Australia) */
+  {0x0C0A,     "es"},  /* Spanish (Modern Sort) (Spain) */
+  {0x0C0C,     "fr"},  /* French (Canada) */
+  {0x0C1A,     "sr"},  /* Serbian (Cyrillic) (Serbia) */
+  {0x0C3B,     "se"},  /* Sami (Northern) (Finland) */
+//{0x0C6B,     ""},    /* Quechua (Peru) */
+  {0x1001,     "ar"},  /* Arabic (Libya) */
+  {0x1004,     "zh-sg"},       /* Chinese (Singapore) */
+  {0x1007,     "de"},  /* German (Luxembourg) */
+  {0x1009,     "en"},  /* English (Canada) */
+  {0x100A,     "es"},  /* Spanish (Guatemala) */
+  {0x100C,     "fr"},  /* French (Switzerland) */
+  {0x101A,     "hr"},  /* Croatian (Latin) (Bosnia and Herzegovina) */
+  {0x103B,     "smj"}, /* Sami (Lule) (Norway) */
+  {0x1401,     "ar"},  /* Arabic (Algeria) */
+//{0x1404,     ""},    /* Chinese (Macao S.A.R.) */
+  {0x1407,     "de"},  /* German (Liechtenstein) */
+  {0x1409,     "en"},  /* English (New Zealand) */
+  {0x140A,     "es"},  /* Spanish (Costa Rica) */
+  {0x140C,     "fr"},  /* French (Luxembourg) */
+  {0x141A,     "bs"},  /* Bosnian (Latin) (Bosnia and Herzegovina) */
+//{0x143B,     ""},    /* Sami (Lule) (Sweden) */
+  {0x1801,     "ar"},  /* Arabic (Morocco) */
+  {0x1809,     "en"},  /* English (Ireland) */
+  {0x180A,     "es"},  /* Spanish (Panama) */
+  {0x180C,     "fr"},  /* French (Principality of Monaco) */
+//{0x181A,     ""},    /* Serbian (Latin) (Bosnia and Herzegovina) */
+  {0x183B,     "sma"}, /* Sami (Southern) (Norway) */
+  {0x1C01,     "ar"},  /* Arabic (Tunisia) */
+  {0x1C09,     "en"},  /* English (South Africa) */
+  {0x1C0A,     "es"},  /* Spanish (Dominican Republic) */
+  {0x1C0C,     "fr"},  /* ??? */
+//{0x1C1A,     ""},    /* Serbian (Cyrillic) (Bosnia and Herzegovina) */
+//{0x1C3B,     ""},    /* Sami (Southern) (Sweden) */
+  {0x2001,     "ar"},  /* Arabic (Oman) */
+  {0x2009,     "en"},  /* English (Jamaica) */
+  {0x200A,     "es"},  /* Spanish (Venezuela) */
+  {0x200C,     "fr"},  /* ??? */
+  {0x201A,     "bs"},  /* Bosnian (Cyrillic) (Bosnia and Herzegovina) */
+  {0x203B,     "sms"}, /* Sami (Skolt) (Finland) */
+  {0x2401,     "ar"},  /* Arabic (Yemen) */
+  {0x2409,     "en"},  /* English (Caribbean) */
+  {0x240A,     "es"},  /* Spanish (Colombia) */
+  {0x240C,     "fr"},  /* ??? */
+  {0x243B,     "smn"}, /* Sami (Inari) (Finland) */
+  {0x2801,     "ar"},  /* Arabic (Syria) */
+  {0x2809,     "en"},  /* English (Belize) */
+  {0x280A,     "es"},  /* Spanish (Peru) */
+  {0x280C,     "fr"},  /* ??? */
+  {0x2C01,     "ar"},  /* Arabic (Jordan) */
+  {0x2C09,     "en"},  /* English (Trinidad and Tobago) */
+  {0x2C0A,     "es"},  /* Spanish (Argentina) */
+  {0x2C0C,     "fr"},  /* ??? */
+  {0x3001,     "ar"},  /* Arabic (Lebanon) */
+  {0x3009,     "en"},  /* English (Zimbabwe) */
+  {0x300A,     "es"},  /* Spanish (Ecuador) */
+  {0x300C,     "fr"},  /* ??? */
+  {0x3401,     "ar"},  /* Arabic (Kuwait) */
+  {0x3409,     "en"},  /* English (Republic of the Philippines) */
+  {0x340A,     "es"},  /* Spanish (Chile) */
+  {0x340C,     "fr"},  /* ??? */
+  {0x3801,     "ar"},  /* Arabic (U.A.E.) */
+  {0x380A,     "es"},  /* Spanish (Uruguay) */
+  {0x380C,     "fr"},  /* ??? */
+  {0x3C01,     "ar"},  /* Arabic (Bahrain) */
+  {0x3C09,     "en"},  /* ??? */
+  {0x3C0A,     "es"},  /* Spanish (Paraguay) */
+  {0x3C0C,     "fr"},  /* ??? */
+  {0x4001,     "ar"},  /* Arabic (Qatar) */
+  {0x4009,     "en"},  /* English (India) */
+  {0x400A,     "es"},  /* Spanish (Bolivia) */
+  {0x4409,     "en"},  /* English (Malaysia) */
+  {0x440A,     "es"},  /* Spanish (El Salvador) */
+  {0x4809,     "en"},  /* English (Singapore) */
+  {0x480A,     "es"},  /* Spanish (Honduras) */
+  {0x4C0A,     "es"},  /* Spanish (Nicaragua) */
+  {0x500A,     "es"},  /* Spanish (Puerto Rico) */
+  {0x540A,     "es"},  /* Spanish (United States) */
+  {0xE40A,     "es"},  /* ??? */
+  {0xE40C,     "fr"},  /* ??? */
+};
+
+static const hb_ot_language_map_t
+hb_mac_language_map[] =
+{
+  {  0,        "en"},  /* English */
+  {  1,        "fr"},  /* French */
+  {  2,        "de"},  /* German */
+  {  3,        "it"},  /* Italian */
+  {  4,        "nl"},  /* Dutch */
+  {  5,        "sv"},  /* Swedish */
+  {  6,        "es"},  /* Spanish */
+  {  7,        "da"},  /* Danish */
+  {  8,        "pt"},  /* Portuguese */
+  {  9,        "no"},  /* Norwegian */
+  { 10,        "he"},  /* Hebrew */
+  { 11,        "ja"},  /* Japanese */
+  { 12,        "ar"},  /* Arabic */
+  { 13,        "fi"},  /* Finnish */
+  { 14,        "el"},  /* Greek */
+  { 15,        "is"},  /* Icelandic */
+  { 16,        "mt"},  /* Maltese */
+  { 17,        "tr"},  /* Turkish */
+  { 18,        "hr"},  /* Croatian */
+  { 19,        "zh-tw"},       /* Chinese (Traditional) */
+  { 20,        "ur"},  /* Urdu */
+  { 21,        "hi"},  /* Hindi */
+  { 22,        "th"},  /* Thai */
+  { 23,        "ko"},  /* Korean */
+  { 24,        "lt"},  /* Lithuanian */
+  { 25,        "pl"},  /* Polish */
+  { 26,        "hu"},  /* Hungarian */
+  { 27,        "et"},  /* Estonian */
+  { 28,        "lv"},  /* Latvian */
+//{ 29,        ""},    /* Sami */
+  { 30,        "fo"},  /* Faroese */
+  { 31,        "fa"},  /* Farsi/Persian */
+  { 32,        "ru"},  /* Russian */
+  { 33,        "zh-cn"},       /* Chinese (Simplified) */
+  { 34,        "nl"},  /* Flemish */
+  { 35,        "ga"},  /* Irish Gaelic */
+  { 36,        "sq"},  /* Albanian */
+  { 37,        "ro"},  /* Romanian */
+  { 38,        "cs"},  /* Czech */
+  { 39,        "sk"},  /* Slovak */
+  { 40,        "sl"},  /* Slovenian */
+  { 41,        "yi"},  /* Yiddish */
+  { 42,        "sr"},  /* Serbian */
+  { 43,        "mk"},  /* Macedonian */
+  { 44,        "bg"},  /* Bulgarian */
+  { 45,        "uk"},  /* Ukrainian */
+  { 46,        "be"},  /* Byelorussian */
+  { 47,        "uz"},  /* Uzbek */
+  { 48,        "kk"},  /* Kazakh */
+  { 49,        "az"},  /* Azerbaijani (Cyrillic script) */
+  { 50,        "az"},  /* Azerbaijani (Arabic script) */
+  { 51,        "hy"},  /* Armenian */
+  { 52,        "ka"},  /* Georgian */
+  { 53,        "mo"},  /* Moldavian */
+  { 54,        "ky"},  /* Kirghiz */
+  { 55,        "tg"},  /* Tajiki */
+  { 56,        "tk"},  /* Turkmen */
+  { 57,        "mn"},  /* Mongolian (Mongolian script) */
+  { 58,        "mn"},  /* Mongolian (Cyrillic script) */
+  { 59,        "ps"},  /* Pashto */
+  { 60,        "ku"},  /* Kurdish */
+  { 61,        "ks"},  /* Kashmiri */
+  { 62,        "sd"},  /* Sindhi */
+  { 63,        "bo"},  /* Tibetan */
+  { 64,        "ne"},  /* Nepali */
+  { 65,        "sa"},  /* Sanskrit */
+  { 66,        "mr"},  /* Marathi */
+  { 67,        "bn"},  /* Bengali */
+  { 68,        "as"},  /* Assamese */
+  { 69,        "gu"},  /* Gujarati */
+  { 70,        "pa"},  /* Punjabi */
+  { 71,        "or"},  /* Oriya */
+  { 72,        "ml"},  /* Malayalam */
+  { 73,        "kn"},  /* Kannada */
+  { 74,        "ta"},  /* Tamil */
+  { 75,        "te"},  /* Telugu */
+  { 76,        "si"},  /* Sinhalese */
+  { 77,        "my"},  /* Burmese */
+  { 78,        "km"},  /* Khmer */
+  { 79,        "lo"},  /* Lao */
+  { 80,        "vi"},  /* Vietnamese */
+  { 81,        "id"},  /* Indonesian */
+  { 82,        "tl"},  /* Tagalog */
+  { 83,        "ms"},  /* Malay (Roman script) */
+  { 84,        "ms"},  /* Malay (Arabic script) */
+  { 85,        "am"},  /* Amharic */
+  { 86,        "ti"},  /* Tigrinya */
+  { 87,        "om"},  /* Galla */
+  { 88,        "so"},  /* Somali */
+  { 89,        "sw"},  /* Swahili */
+  { 90,        "rw"},  /* Kinyarwanda/Ruanda */
+  { 91,        "rn"},  /* Rundi */
+  { 92,        "ny"},  /* Nyanja/Chewa */
+  { 93,        "mg"},  /* Malagasy */
+  { 94,        "eo"},  /* Esperanto */
+  {128,        "cy"},  /* Welsh */
+  {129,        "eu"},  /* Basque */
+  {130,        "ca"},  /* Catalan */
+  {131,        "la"},  /* Latin */
+  {132,        "qu"},  /* Quechua */
+  {133,        "gn"},  /* Guarani */
+  {134,        "ay"},  /* Aymara */
+  {135,        "tt"},  /* Tatar */
+  {136,        "ug"},  /* Uighur */
+  {137,        "dz"},  /* Dzongkha */
+  {138,        "jw"},  /* Javanese (Roman script) */
+  {139,        "su"},  /* Sundanese (Roman script) */
+  {140,        "gl"},  /* Galician */
+  {141,        "af"},  /* Afrikaans */
+  {142,        "br"},  /* Breton */
+  {143,        "iu"},  /* Inuktitut */
+  {144,        "gd"},  /* Scottish Gaelic */
+  {145,        "gv"},  /* Manx Gaelic */
+  {146,        "ga"},  /* Irish Gaelic (with dot above) */
+  {147,        "to"},  /* Tongan */
+  {148,        "el"},  /* Greek (polytonic) */
+  {149,        "ik"},  /* Greenlandic */
+  {150,        "az"},  /* Azerbaijani (Roman script) */
+};
+
+
+static hb_language_t
+_hb_ot_name_language_for (unsigned int code,
+                         const hb_ot_language_map_t *array,
+                         unsigned int len)
+{
+  const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
+                                     hb_bsearch (&code,
+                                                 array,
+                                                 len,
+                                                 sizeof (array[0]),
+                                                 hb_ot_language_map_t::cmp);
+
+  if (entry)
+    return hb_language_from_string (entry->lang, -1);
+
+  return HB_LANGUAGE_INVALID;
+}
+
+hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                  hb_ms_language_map,
+                                  ARRAY_LENGTH (hb_ms_language_map));
+}
+
+hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                  hb_mac_language_map,
+                                  ARRAY_LENGTH (hb_mac_language_map));
+}
diff --git a/src/hb-ot-name-language.hh b/src/hb-ot-name-language.hh
new file mode 100644 (file)
index 0000000..903076c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_NAME_LANGUAGE_HH
+#define HB_OT_NAME_LANGUAGE_HH
+
+#include "hb.hh"
+
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code);
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code);
+
+
+#endif /* HB_OT_NAME_LANGUAGE_HH */
index bff85df..c8ababd 100644 (file)
 #ifndef HB_OT_NAME_TABLE_HH
 #define HB_OT_NAME_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-name-language.hh"
+#include "hb-aat-layout.hh"
 
 
 namespace OT {
 
 
+#define entry_score var.u16[0]
+#define entry_index var.u16[1]
+
+
 /*
  * name -- Naming
  * https://docs.microsoft.com/en-us/typography/opentype/spec/name
  */
 #define HB_OT_TAG_name HB_TAG('n','a','m','e')
 
+#define UNSUPPORTED    42
 
 struct NameRecord
 {
-  static int cmp (const void *pa, const void *pb)
+  hb_language_t language (hb_face_t *face) const
   {
-    const NameRecord *a = (const NameRecord *) pa;
-    const NameRecord *b = (const NameRecord *) pb;
-    int ret;
-    ret = b->platformID.cmp (a->platformID);
-    if (ret) return ret;
-    ret = b->encodingID.cmp (a->encodingID);
-    if (ret) return ret;
-    ret = b->languageID.cmp (a->languageID);
-    if (ret) return ret;
-    ret = b->nameID.cmp (a->nameID);
-    if (ret) return ret;
-    return 0;
+    unsigned int p = platformID;
+    unsigned int l = languageID;
+
+    if (p == 3)
+      return _hb_ot_name_language_for_ms_code (l);
+
+    if (p == 1)
+      return _hb_ot_name_language_for_mac_code (l);
+
+    if (p == 0)
+      return _hb_aat_language_get (face, l);
+
+    return HB_LANGUAGE_INVALID;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  uint16_t score () const
+  {
+    /* Same order as in cmap::find_best_subtable(). */
+    unsigned int p = platformID;
+    unsigned int e = encodingID;
+
+    /* 32-bit. */
+    if (p == 3 && e == 10) return 0;
+    if (p == 0 && e ==  6) return 1;
+    if (p == 0 && e ==  4) return 2;
+
+    /* 16-bit. */
+    if (p == 3 && e ==  1) return 3;
+    if (p == 0 && e ==  3) return 4;
+    if (p == 0 && e ==  2) return 5;
+    if (p == 0 && e ==  1) return 6;
+    if (p == 0 && e ==  0) return 7;
+
+    /* Symbol. */
+    if (p == 3 && e ==  0) return 8;
+
+    /* We treat all Mac Latin names as ASCII only. */
+    if (p == 1 && e ==  0) return 10; /* 10 is magic number :| */
+
+    return UNSUPPORTED;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
@@ -75,62 +110,168 @@ struct NameRecord
   DEFINE_SIZE_STATIC (12);
 };
 
+static int
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
+{
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  /* Compare by name_id, then language. */
+
+  if (a->name_id != b->name_id)
+    return a->name_id < b->name_id ? -1 : +1;
+
+  if (a->language == b->language) return 0;
+  if (!a->language) return -1;
+  if (!b->language) return +1;
+  return strcmp (hb_language_to_string (a->language),
+                hb_language_to_string (b->language));
+}
+
+static int
+_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+{
+  /* Compare by name_id, then language, then score, then index. */
+
+  int v = _hb_ot_name_entry_cmp_key (pa, pb);
+  if (v)
+    return v;
+
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  if (a->entry_score != b->entry_score)
+    return a->entry_score < b->entry_score ? -1 : +1;
+
+  if (a->entry_index != b->entry_index)
+    return a->entry_index < b->entry_index ? -1 : +1;
+
+  return 0;
+}
+
 struct name
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_name;
-
-  inline unsigned int get_name (unsigned int platform_id,
-                               unsigned int encoding_id,
-                               unsigned int language_id,
-                               unsigned int name_id,
-                               void *buffer,
-                               unsigned int buffer_length) const
-  {
-    NameRecord key;
-    key.platformID.set (platform_id);
-    key.encodingID.set (encoding_id);
-    key.languageID.set (language_id);
-    key.nameID.set (name_id);
-    NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
-
-    if (!match)
-      return 0;
-
-    unsigned int length = MIN (buffer_length, (unsigned int) match->length);
-    memcpy (buffer, (char *) this + stringOffset + match->offset, length);
-    return length;
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
 
-  inline unsigned int get_size (void) const
-  { return min_size + count * nameRecord[0].min_size; }
+  unsigned int get_size () const
+  { return min_size + count * nameRecordZ.item_size; }
 
-  inline bool sanitize_records (hb_sanitize_context_t *c) const {
+  bool sanitize_records (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    char *string_pool = (char *) this + stringOffset;
+    const void *string_pool = (this+stringOffset).arrayZ;
     unsigned int _count = count;
+    /* Move to run-time?! */
     for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
+      if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                  likely (format == 0 || format == 1) &&
-                 c->check_array (nameRecord, nameRecord[0].static_size, count) &&
-                 sanitize_records (c));
+                 c->check_array (nameRecordZ.arrayZ, count) &&
+                 c->check_range (this, stringOffset));
   }
 
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<name> (face);
+      assert (this->table.get_length () >= this->table->stringOffset);
+      this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
+      this->pool_len = this->table.get_length () - this->table->stringOffset;
+      const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
+                                                   this->table->count);
+
+      this->names.init ();
+      this->names.alloc (all_names.length);
+
+      for (unsigned int i = 0; i < all_names.length; i++)
+      {
+       hb_ot_name_entry_t *entry = this->names.push ();
+
+       entry->name_id = all_names[i].nameID;
+       entry->language = all_names[i].language (face);
+       entry->entry_score =  all_names[i].score ();
+       entry->entry_index = i;
+      }
+
+      this->names.qsort (_hb_ot_name_entry_cmp);
+      /* Walk and pick best only for each name_id,language pair,
+       * while dropping unsupported encodings. */
+      unsigned int j = 0;
+      for (unsigned int i = 0; i < this->names.length; i++)
+      {
+        if (this->names[i].entry_score == UNSUPPORTED ||
+           this->names[i].language == HB_LANGUAGE_INVALID)
+         continue;
+        if (i &&
+           this->names[i - 1].name_id  == this->names[i].name_id &&
+           this->names[i - 1].language == this->names[i].language)
+         continue;
+       this->names[j++] = this->names[i];
+      }
+      this->names.resize (j);
+    }
+
+    void fini ()
+    {
+      this->names.fini ();
+      this->table.destroy ();
+    }
+
+    int get_index (hb_ot_name_id_t   name_id,
+                         hb_language_t     language,
+                         unsigned int     *width=nullptr) const
+    {
+      const hb_ot_name_entry_t key = {name_id, {0}, language};
+      const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *)
+                                       hb_bsearch (&key,
+                                                   (const hb_ot_name_entry_t *) this->names,
+                                                   this->names.length,
+                                                   sizeof (key),
+                                                   _hb_ot_name_entry_cmp_key);
+      if (!entry)
+        return -1;
+
+      if (width)
+        *width = entry->entry_score < 10 ? 2 : 1;
+
+      return entry->entry_index;
+    }
+
+    hb_bytes_t get_name (unsigned int idx) const
+    {
+      const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
+      const NameRecord &record = all_names[idx];
+      const hb_bytes_t string_pool (pool, pool_len);
+      return string_pool.sub_array (record.offset, record.length);
+    }
+
+    private:
+    const char *pool;
+    unsigned int pool_len;
+    public:
+    hb_blob_ptr_t<name> table;
+    hb_vector_t<hb_ot_name_entry_t> names;
+  };
+
   /* We only implement format 0 for now. */
   HBUINT16     format;                 /* Format selector (=0/1). */
   HBUINT16     count;                  /* Number of name records. */
-  Offset16     stringOffset;           /* Offset to start of string storage (from start of table). */
-  NameRecord   nameRecord[VAR];        /* The name records where count is the number of records. */
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+               stringOffset;           /* Offset to start of string storage (from start of table). */
+  UnsizedArrayOf<NameRecord>
+               nameRecordZ;            /* The name records where count is the number of records. */
   public:
-  DEFINE_SIZE_ARRAY (6, nameRecord);
+  DEFINE_SIZE_ARRAY (6, nameRecordZ);
 };
 
+struct name_accelerator_t : name::accelerator_t {};
 
 } /* namespace OT */
 
diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc
new file mode 100644 (file)
index 0000000..907ae6a
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#include "hb-ot-name-table.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-utf.hh"
+
+
+/**
+ * SECTION:hb-ot-name
+ * @title: hb-ot-name
+ * @short_description: OpenType font name information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching name strings from OpenType fonts.
+ **/
+
+
+/**
+ * hb_ot_name_list_names:
+ * @face: font face.
+ * @num_entries: (out) (allow-none): number of returned entries.
+ *
+ * Enumerates all available name IDs and language combinations. Returned
+ * array is owned by the @face and should not be modified.  It can be
+ * used as long as @face is alive.
+ *
+ * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Since: 2.1.0
+ **/
+const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                      unsigned int *num_entries /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+  if (num_entries) *num_entries = name.names.length;
+  return (const hb_ot_name_entry_t *) name.names;
+}
+
+
+template <typename in_utf_t, typename out_utf_t>
+static inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t                       bytes,
+                       unsigned int                    *text_size /* IN/OUT */,
+                       typename out_utf_t::codepoint_t *text /* OUT */)
+{
+  unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+  const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+  const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+  typename out_utf_t::codepoint_t *dst = text;
+
+  hb_codepoint_t unicode;
+  const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+  if (text_size && *text_size)
+  {
+    (*text_size)--; /* Same room for NUL-termination. */
+    const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+    while (src < src_end && dst < dst_end)
+    {
+      const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+      typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+      if (dst_next == dst)
+        break; /* Out-of-room. */
+
+      dst = dst_next;
+      src = src_next;
+    };
+
+    *text_size = dst - text;
+    *dst = 0; /* NUL-terminate. */
+  }
+
+  /* Accumulate length of rest. */
+  unsigned int dst_len = dst - text;
+  while (src < src_end)
+  {
+    src = in_utf_t::next (src, src_end, &unicode, replacement);
+    dst_len += out_utf_t::encode_len (unicode);
+  };
+  return dst_len;
+}
+
+template <typename utf_t>
+static inline unsigned int
+hb_ot_name_get_utf (hb_face_t       *face,
+                   hb_ot_name_id_t  name_id,
+                   hb_language_t    language,
+                   unsigned int    *text_size /* IN/OUT */,
+                   typename utf_t::codepoint_t *text /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+
+  if (!language)
+    language = hb_language_from_string ("en", 2);
+
+  unsigned int width;
+  int idx = name.get_index (name_id, language, &width);
+  if (idx != -1)
+  {
+    hb_bytes_t bytes = name.get_name (idx);
+
+    if (width == 2) /* UTF16-BE */
+      return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+
+    if (width == 1) /* ASCII */
+      return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+  }
+
+  if (text_size)
+  {
+    if (*text_size)
+      *text = 0;
+    *text_size = 0;
+  }
+  return 0;
+}
+
+/**
+ * hb_ot_name_get_utf8:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-8 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                    hb_ot_name_id_t  name_id,
+                    hb_language_t    language,
+                    unsigned int    *text_size /* IN/OUT */,
+                    char            *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
+                                       (hb_utf8_t::codepoint_t *) text);
+}
+
+/**
+ * hb_ot_name_get_utf16:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-16 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     uint16_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
+}
+
+/**
+ * hb_ot_name_get_utf32:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-32 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     uint32_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
+}
diff --git a/src/hb-ot-name.h b/src/hb-ot-name.h
new file mode 100644 (file)
index 0000000..3b4ad58
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi.
+ *
+ *  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.
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_NAME_H
+#define HB_OT_NAME_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * hb_ot_name_id_t:
+ * @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
+ *
+ * An integral type representing an OpenType 'name' table name identifier.
+ * There are predefined name IDs, as well as name IDs return from other
+ * API.  These can be used to fetch name strings from a font face.
+ *
+ * Since: 2.0.0
+ **/
+enum
+{
+  HB_OT_NAME_ID_COPYRIGHT              = 0,
+  HB_OT_NAME_ID_FONT_FAMILY            = 1,
+  HB_OT_NAME_ID_FONT_SUBFAMILY         = 2,
+  HB_OT_NAME_ID_UNIQUE_ID              = 3,
+  HB_OT_NAME_ID_FULL_NAME              = 4,
+  HB_OT_NAME_ID_VERSION_STRING         = 5,
+  HB_OT_NAME_ID_POSTSCRIPT_NAME                = 6,
+  HB_OT_NAME_ID_TRADEMARK              = 7,
+  HB_OT_NAME_ID_MANUFACTURER           = 8,
+  HB_OT_NAME_ID_DESIGNER               = 9,
+  HB_OT_NAME_ID_DESCRIPTION            = 10,
+  HB_OT_NAME_ID_VENDOR_URL             = 11,
+  HB_OT_NAME_ID_DESIGNER_URL           = 12,
+  HB_OT_NAME_ID_LICENSE                        = 13,
+  HB_OT_NAME_ID_LICENSE_URL            = 14,
+/*HB_OT_NAME_ID_RESERVED               = 15,*/
+  HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY     = 16,
+  HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY  = 17,
+  HB_OT_NAME_ID_MAC_FULL_NAME          = 18,
+  HB_OT_NAME_ID_SAMPLE_TEXT            = 19,
+  HB_OT_NAME_ID_CID_FINDFONT_NAME      = 20,
+  HB_OT_NAME_ID_WWS_FAMILY             = 21,
+  HB_OT_NAME_ID_WWS_SUBFAMILY          = 22,
+  HB_OT_NAME_ID_LIGHT_BACKGROUND       = 23,
+  HB_OT_NAME_ID_DARK_BACKGROUND                = 24,
+  HB_OT_NAME_ID_VARIATIONS_PS_PREFIX   = 25,
+
+  HB_OT_NAME_ID_INVALID                        = 0xFFFF
+};
+
+typedef unsigned int hb_ot_name_id_t;
+
+
+/**
+ * hb_ot_name_entry_t:
+ * @name_id: name ID
+ * @language: language
+ *
+ * Structure representing a name ID in a particular language.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_name_entry_t
+{
+  hb_ot_name_id_t name_id;
+  /*< private >*/
+  hb_var_int_t    var;
+  /*< public >*/
+  hb_language_t   language;
+} hb_ot_name_entry_t;
+
+HB_EXTERN const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                      unsigned int *num_entries /* OUT */);
+
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                    hb_ot_name_id_t  name_id,
+                    hb_language_t    language,
+                    unsigned int    *text_size /* IN/OUT */,
+                    char            *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     uint16_t        *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     uint32_t        *text      /* OUT */);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_NAME_H */
index c52b7eb..68dd63e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2011,2012  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
 #ifndef HB_OT_OS2_TABLE_HH
 #define HB_OT_OS2_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
-#include "hb-subset-plan.hh"
 
-namespace OT {
+#include "hb-set.hh"
 
 /*
  * OS/2 and Windows Metrics
  * https://docs.microsoft.com/en-us/typography/opentype/spec/os2
  */
-#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
+#define HB_OT_TAG_OS2 HB_TAG('O','S','/','2')
+
+
+namespace OT {
 
-struct os2
+struct OS2V1Tail
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_os2;
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT32     ulCodePageRange1;
+  HBUINT32     ulCodePageRange2;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+struct OS2V2Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  public:
+  HBINT16      sxHeight;
+  HBINT16      sCapHeight;
+  HBUINT16     usDefaultChar;
+  HBUINT16     usBreakChar;
+  HBUINT16     usMaxContext;
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct OS2V5Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16     usLowerOpticalPointSize;
+  HBUINT16     usUpperOpticalPointSize;
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct OS2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2;
+
+  bool has_data () const { return this != &Null (OS2); }
+
+  const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
+  const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
+  const OS2V5Tail &v5 () const { return version >= 5 ? v5X : Null (OS2V5Tail); }
+
+  enum selection_flag_t {
+    ITALIC             = 1u<<0,
+    UNDERSCORE         = 1u<<1,
+    NEGATIVE           = 1u<<2,
+    OUTLINED           = 1u<<3,
+    STRIKEOUT          = 1u<<4,
+    BOLD               = 1u<<5,
+    REGULAR            = 1u<<6,
+    USE_TYPO_METRICS   = 1u<<7,
+    WWS                        = 1u<<8,
+    OBLIQUE            = 1u<<9
+  };
+
+  bool is_italic () const       { return fsSelection & ITALIC; }
+  bool is_oblique () const      { return fsSelection & OBLIQUE; }
+  bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
+
+  enum width_class_t {
+    FWIDTH_ULTRA_CONDENSED     = 1, /* 50% */
+    FWIDTH_EXTRA_CONDENSED     = 2, /* 62.5% */
+    FWIDTH_CONDENSED           = 3, /* 75% */
+    FWIDTH_SEMI_CONDENSED      = 4, /* 87.5% */
+    FWIDTH_NORMAL              = 5, /* 100% */
+    FWIDTH_SEMI_EXPANDED       = 6, /* 112.5% */
+    FWIDTH_EXPANDED            = 7, /* 125% */
+    FWIDTH_EXTRA_EXPANDED      = 8, /* 150% */
+    FWIDTH_ULTRA_EXPANDED      = 9  /* 200% */
+  };
+
+  float get_width () const
+  {
+    switch (usWidthClass) {
+    case FWIDTH_ULTRA_CONDENSED:return 50.f;
+    case FWIDTH_EXTRA_CONDENSED:return 62.5f;
+    case FWIDTH_CONDENSED:     return 75.f;
+    case FWIDTH_SEMI_CONDENSED:        return 87.5f;
+    default:
+    case FWIDTH_NORMAL:                return 100.f;
+    case FWIDTH_SEMI_EXPANDED: return 112.5f;
+    case FWIDTH_EXPANDED:      return 125.f;
+    case FWIDTH_EXTRA_EXPANDED:        return 150.f;
+    case FWIDTH_ULTRA_EXPANDED:        return 200.f;
+    }
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
     hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
     // TODO(grieger): move to hb_blob_copy_writable_or_fail
     hb_blob_destroy (os2_blob);
 
-    OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
+    OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
     if (unlikely (!os2_prime)) {
       hb_blob_destroy (os2_prime_blob);
       return false;
@@ -68,41 +164,41 @@ struct os2
     os2_prime->usLastCharIndex.set (max_cp);
 
     _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
-    bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
+    bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
 
     hb_blob_destroy (os2_prime_blob);
     return result;
   }
 
-  inline void _update_unicode_ranges (const hb_set_t *codepoints,
-                                      HBUINT32 ulUnicodeRange[4]) const
+  void _update_unicode_ranges (const hb_set_t *codepoints,
+                              HBUINT32 ulUnicodeRange[4]) const
   {
     for (unsigned int i = 0; i < 4; i++)
       ulUnicodeRange[i].set (0);
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (codepoints->next (&cp)) {
-      unsigned int bit = hb_get_unicode_range_bit (cp);
+      unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
       if (bit < 128)
       {
-        unsigned int block = bit / 32;
-        unsigned int bit_in_block = bit % 32;
-        unsigned int mask = 1 << bit_in_block;
-        ulUnicodeRange[block].set (ulUnicodeRange[block] | mask);
+       unsigned int block = bit / 32;
+       unsigned int bit_in_block = bit % 32;
+       unsigned int mask = 1 << bit_in_block;
+       ulUnicodeRange[block].set (ulUnicodeRange[block] | mask);
       }
       if (cp >= 0x10000 && cp <= 0x110000)
       {
-        /* the spec says that bit 57 ("Non Plane 0") implies that there's
-           at least one codepoint beyond the BMP; so I also include all
-           the non-BMP codepoints here */
-        ulUnicodeRange[1].set (ulUnicodeRange[1] | (1 << 25));
+       /* the spec says that bit 57 ("Non Plane 0") implies that there's
+          at least one codepoint beyond the BMP; so I also include all
+          the non-BMP codepoints here */
+       ulUnicodeRange[1].set (ulUnicodeRange[1] | (1 << 25));
       }
     }
   }
 
-  static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
-                                                 uint16_t *min_cp, /* OUT */
-                                                 uint16_t *max_cp  /* OUT */)
+  static void find_min_and_max_codepoint (const hb_set_t *codepoints,
+                                                uint16_t *min_cp, /* OUT */
+                                                uint16_t *max_cp  /* OUT */)
   {
     *min_cp = codepoints->get_min ();
     *max_cp = codepoints->get_max ();
@@ -119,17 +215,21 @@ struct os2
   };
 
   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
-  inline font_page_t get_font_page () const
+  font_page_t get_font_page () const
+  { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    if (version != 0)
-      return (font_page_t) 0;
-    return (font_page_t) (fsSelection & 0xFF00);
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
+    return_trace (true);
   }
 
   public:
   HBUINT16     version;
-
-  /* Version 0 */
   HBINT16      xAvgCharWidth;
   HBUINT16     usWeightClass;
   HBUINT16     usWidthClass;
@@ -156,24 +256,11 @@ struct os2
   HBINT16      sTypoLineGap;
   HBUINT16     usWinAscent;
   HBUINT16     usWinDescent;
-
-  /* Version 1 */
-  //HBUINT32   ulCodePageRange1;
-  //HBUINT32   ulCodePageRange2;
-
-  /* Version 2 */
-  //HBINT16    sxHeight;
-  //HBINT16    sCapHeight;
-  //HBUINT16   usDefaultChar;
-  //HBUINT16   usBreakChar;
-  //HBUINT16   usMaxContext;
-
-  /* Version 5 */
-  //HBUINT16   usLowerOpticalPointSize;
-  //HBUINT16   usUpperOpticalPointSize;
-
+  OS2V1Tail    v1X;
+  OS2V2Tail    v2X;
+  OS2V5Tail    v5X;
   public:
-  DEFINE_SIZE_STATIC (78);
+  DEFINE_SIZE_MIN (78);
 };
 
 } /* namespace OT */
index 9b32cfa..b0ccd00 100644 (file)
 #ifndef HB_OT_OS2_UNICODE_RANGES_HH
 #define HB_OT_OS2_UNICODE_RANGES_HH
 
-#include "hb-private.hh"
-#include "hb-dsalgs.hh"
+#include "hb.hh"
 
 namespace OT {
 
-struct Range {
+struct OS2Range
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const OS2Range *range = (OS2Range *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
   hb_codepoint_t start;
   hb_codepoint_t end;
   unsigned int bit;
 };
 
-/* Note: The contents of this array was generated using src/gen-unicode-ranges.py. */
-static Range os2UnicodeRangesSorted[] =
+/* Note: The contents of this array was generated using gen-os2-unicode-ranges.py. */
+static const OS2Range _hb_os2_unicode_ranges[] =
 {
   {     0x0,     0x7F,   0}, // Basic Latin
   {    0x80,     0xFF,   1}, // Latin-1 Supplement
@@ -212,31 +226,17 @@ static Range os2UnicodeRangesSorted[] =
   {0x100000, 0x10FFFD,  90}, // Private Use (plane 16)
 };
 
-static int
-_compare_range (const void *_key, const void *_item, void *_arg)
-{
-  hb_codepoint_t cp = *((hb_codepoint_t *) _key);
-  const Range *range = (Range *) _item;
-
-  if (cp < range->start)
-    return -1;
-  else if (cp <= range->end)
-    return 0;
-  else
-    return 1;
-}
-
 /**
- * hb_get_unicode_range_bit:
- * Returns the bit to be set in os/2 ulUnicodeRange for a given codepoint.
+ * _hb_ot_os2_get_unicode_range_bit:
+ * Returns the bit to be set in os/2 ulUnicodeOS2Range for a given codepoint.
  **/
 static unsigned int
-hb_get_unicode_range_bit (hb_codepoint_t cp)
+_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
 {
-  Range *range = (Range*) hb_bsearch_r (&cp, os2UnicodeRangesSorted,
-                                        sizeof (os2UnicodeRangesSorted) / sizeof(Range),
-                                        sizeof(Range),
-                                        _compare_range, nullptr);
+  OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges,
+                                           ARRAY_LENGTH (_hb_os2_unicode_ranges),
+                                           sizeof (OS2Range),
+                                           OS2Range::cmp);
   if (range != nullptr)
     return range->bit;
   return -1;
index dbbb97e..b4df8aa 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_POST_MACROMAN_HH
 #if 0 /* Make checks happy. */
 #define HB_OT_POST_MACROMAN_HH
-#include "hb-private.hh"
+#include "hb.hh"
 #endif
 
 
index 5f42751..43c1143 100644 (file)
@@ -27,9 +27,7 @@
 #ifndef HB_OT_POST_TABLE_HH
 #define HB_OT_POST_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-dsalgs.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 #define HB_STRING_ARRAY_NAME format1_names
 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
@@ -51,47 +49,39 @@ namespace OT {
 
 struct postV2Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  friend struct post;
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (glyphNameIndex.sanitize (c));
   }
 
-  ArrayOf<HBUINT16>glyphNameIndex;     /* This is not an offset, but is the
+  protected:
+  ArrayOf<HBUINT16>    glyphNameIndex; /* This is not an offset, but is the
                                         * ordinal number of the glyph in 'post'
                                         * string tables. */
-  HBUINT8              namesX[VAR];            /* Glyph names with length bytes [variable]
+/*UnsizedArrayOf<HBUINT8>
+                       namesX;*/       /* Glyph names with length bytes [variable]
                                         * (a Pascal string). */
 
-  DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
+  public:
+  DEFINE_SIZE_ARRAY (2, glyphNameIndex);
 };
 
 struct post
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_post;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    if (version.to_int () == 0x00020000)
-    {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
-      return_trace (v2.sanitize (c));
-    }
-    return_trace (true);
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     unsigned int post_prime_length;
-    hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
-    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size);
+    hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
+    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
     post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
     hb_blob_destroy (post_blob);
 
-    if (unlikely (!post_prime || post_prime_length != post::static_size))
+    if (unlikely (!post_prime || post_prime_length != post::min_size))
     {
       hb_blob_destroy (post_prime_blob);
       DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
@@ -107,63 +97,58 @@ struct post
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       index_to_offset.init ();
 
-      blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
-      const post *table = blob->as<post> ();
-      unsigned int table_length = blob->length;
+      table = hb_sanitize_context_t ().reference_table<post> (face);
+      unsigned int table_length = table.get_length ();
 
       version = table->version.to_int ();
-      if (version != 0x00020000)
-        return;
+      if (version != 0x00020000) return;
 
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
+      const postV2Tail &v2 = table->v2X;
 
       glyphNameIndex = &v2.glyphNameIndex;
       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
 
-      const uint8_t *end = (uint8_t *) table + table_length;
-      for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
+      const uint8_t *end = (const uint8_t *) (const void *) table + table_length;
+      for (const uint8_t *data = pool;
+          index_to_offset.length < 65535 && data < end && data + *data < end;
+          data += 1 + *data)
        index_to_offset.push (data - pool);
     }
-    inline void fini (void)
+    void fini ()
     {
       index_to_offset.fini ();
-      free (gids_sorted_by_name);
+      free (gids_sorted_by_name.get ());
+      table.destroy ();
     }
 
-    inline bool get_glyph_name (hb_codepoint_t glyph,
-                               char *buf, unsigned int buf_len) const
+    bool get_glyph_name (hb_codepoint_t glyph,
+                        char *buf, unsigned int buf_len) const
     {
       hb_bytes_t s = find_glyph_name (glyph);
-      if (!s.len)
-        return false;
-      if (!buf_len)
-       return true;
-      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
-        return false;
-      strncpy (buf, s.bytes, s.len);
-      buf[s.len] = '\0';
+      if (!s.length) return false;
+      if (!buf_len) return true;
+      unsigned int len = MIN (buf_len - 1, s.length);
+      strncpy (buf, s.arrayZ, len);
+      buf[len] = '\0';
       return true;
     }
 
-    inline bool get_glyph_from_name (const char *name, int len,
-                                    hb_codepoint_t *glyph) const
+    bool get_glyph_from_name (const char *name, int len,
+                             hb_codepoint_t *glyph) const
     {
       unsigned int count = get_glyph_count ();
-      if (unlikely (!count))
-        return false;
+      if (unlikely (!count)) return false;
 
-      if (len < 0)
-       len = strlen (name);
+      if (len < 0) len = strlen (name);
 
-      if (unlikely (!len))
-       return false;
+      if (unlikely (!len)) return false;
 
     retry:
-      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
+      uint16_t *gids = gids_sorted_by_name.get ();
 
       if (unlikely (!gids))
       {
@@ -175,14 +160,16 @@ struct post
          gids[i] = i;
        hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
 
-       if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
+       if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
+       {
          free (gids);
          goto retry;
        }
       }
 
       hb_bytes_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
+                                                            sizeof (gids[0]), cmp_key, (void *) this);
       if (gid)
       {
        *glyph = *gid;
@@ -194,18 +181,18 @@ struct post
 
     protected:
 
-    inline unsigned int get_glyph_count (void) const
+    unsigned int get_glyph_count () const
     {
       if (version == 0x00010000)
-        return NUM_FORMAT1_NAMES;
+       return NUM_FORMAT1_NAMES;
 
       if (version == 0x00020000)
-        return glyphNameIndex->len;
+       return glyphNameIndex->len;
 
       return 0;
     }
 
-    static inline int cmp_gids (const void *pa, const void *pb, void *arg)
+    static int cmp_gids (const void *pa, const void *pb, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       uint16_t a = * (const uint16_t *) pa;
@@ -213,7 +200,7 @@ struct post
       return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
     }
 
-    static inline int cmp_key (const void *pk, const void *po, void *arg)
+    static int cmp_key (const void *pk, const void *po, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       const hb_bytes_t *key = (const hb_bytes_t *) pk;
@@ -221,7 +208,7 @@ struct post
       return thiz->find_glyph_name (o).cmp (*key);
     }
 
-    inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
+    hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
     {
       if (version == 0x00010000)
       {
@@ -239,9 +226,9 @@ struct post
        return format1_names (index);
       index -= NUM_FORMAT1_NAMES;
 
-      if (index >= index_to_offset.len)
+      if (index >= index_to_offset.length)
        return hb_bytes_t ();
-      unsigned int offset = index_to_offset.arrayZ[index];
+      unsigned int offset = index_to_offset[index];
 
       const uint8_t *data = pool + offset;
       unsigned int name_length = *data;
@@ -251,14 +238,23 @@ struct post
     }
 
     private:
-    hb_blob_t *blob;
+    hb_blob_ptr_t<post> table;
     uint32_t version;
     const ArrayOf<HBUINT16> *glyphNameIndex;
-    hb_vector_t<uint32_t, 1> index_to_offset;
+    hb_vector_t<uint32_t> index_to_offset;
     const uint8_t *pool;
-    mutable uint16_t *gids_sorted_by_name;
+    hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         (version.to_int () == 0x00010000 ||
+                          (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+                          version.to_int () == 0x00030000)));
+  }
+
   public:
   FixedVersion<>version;               /* 0x00010000 for version 1.0
                                         * 0x00020000 for version 2.0
@@ -291,10 +287,12 @@ struct post
                                         * is downloaded as a Type 1 font. */
   HBUINT32     maxMemType1;            /* Maximum memory usage when an OpenType font
                                         * is downloaded as a Type 1 font. */
-/*postV2Tail   v2[VAR];*/
-  DEFINE_SIZE_STATIC (32);
+  postV2Tail   v2X;
+  DEFINE_SIZE_MIN (32);
 };
 
+struct post_accelerator_t : post::accelerator_t {};
+
 } /* namespace OT */
 
 
index 5a257f0..2a1f2f8 100644 (file)
@@ -27,9 +27,9 @@
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape.hh"
 #include "hb-ot-layout-gsub-table.hh"
 
 
@@ -79,18 +79,15 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
   hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
 
-  OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
-  OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_single (&c,
                                       OT::LookupFlag::IgnoreMarks,
-                                      glyphs_supplier,
-                                      substitutes_supplier,
-                                      num_glyphs);
+                                      hb_array (glyphs, num_glyphs),
+                                      hb_array (substitutes, num_glyphs));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -155,25 +152,18 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
   if (!num_ligatures)
     return nullptr;
 
-  OT::Supplier<OT::GlyphID>   first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
-  OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
-  OT::Supplier<OT::GlyphID>   ligatures_supplier                         (ligature_list, num_ligatures);
-  OT::Supplier<unsigned int > component_count_supplier                   (component_count_list, num_ligatures);
-  OT::Supplier<OT::GlyphID>   component_supplier                         (component_list, num_ligatures);
 
   /* 16 bytes per ligature ought to be enough... */
   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_ligature (&c,
                                         OT::LookupFlag::IgnoreMarks,
-                                        first_glyphs_supplier,
-                                        ligature_per_first_glyph_count_supplier,
-                                        num_first_glyphs,
-                                        ligatures_supplier,
-                                        component_count_supplier,
-                                        component_supplier);
-
+                                        hb_array (first_glyphs, num_first_glyphs),
+                                        hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
+                                        hb_array (ligature_list, num_ligatures),
+                                        hb_array (component_count_list, num_ligatures),
+                                        hb_array (component_list, num_ligatures));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -195,19 +185,15 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
 
 struct arabic_fallback_plan_t
 {
-  ASSERT_POD ();
-
   unsigned int num_lookups;
   bool free_lookups;
 
   hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
   OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+  OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
 };
 
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
+#if defined(_WIN32) && !defined(HB_NO_WIN1256)
 #define HB_WITH_WIN1256
 #endif
 
@@ -215,16 +201,20 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
 #include "hb-ot-shape-complex-arabic-win1256.hh"
 #endif
 
-struct ManifestLookup {
+struct ManifestLookup
+{
+  public:
   OT::Tag tag;
   OT::OffsetTo<OT::SubstLookup> lookupOffset;
+  public:
+  DEFINE_SIZE_STATIC (6);
 };
 typedef OT::ArrayOf<ManifestLookup> Manifest;
 
 static bool
-arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
-                                  const hb_ot_shape_plan_t *plan,
-                                  hb_font_t *font)
+arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
+                                  const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                  hb_font_t *font HB_UNUSED)
 {
 #ifdef HB_WITH_WIN1256
   /* Does this font look like it's Windows-1256-encoded? */
@@ -299,7 +289,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 {
   arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
-    return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+    return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 
   fallback_plan->num_lookups = 0;
   fallback_plan->free_lookups = false;
@@ -314,14 +304,15 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
   if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
     return fallback_plan;
 
+  assert (fallback_plan->num_lookups == 0);
   free (fallback_plan);
-  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+  return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 }
 
 static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
-  if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
+  if (!fallback_plan || fallback_plan->num_lookups == 0)
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
diff --git a/src/hb-ot-shape-complex-arabic-private.hh b/src/hb-ot-shape-complex-arabic-private.hh
deleted file mode 100644 (file)
index fcedc7d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  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.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-struct arabic_shape_plan_t;
-
-HB_INTERNAL void *
-data_create_arabic (const hb_ot_shape_plan_t *plan);
-
-HB_INTERNAL void
-data_destroy_arabic (void *data);
-
-HB_INTERNAL void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-                        hb_buffer_t               *buffer,
-                        hb_script_t                script);
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */
index 54c6cdc..b15e145 100644 (file)
@@ -313,7 +313,7 @@ OT_TABLE_END
  * Include a second time to get the table data...
  */
 #if 0
-#include "hb-private.hh" /* Make check-includes.sh happy. */
+#include "hb.hh" /* Make check-includes.sh happy. */
 #endif
 #ifdef OT_MEASURE
 #include "hb-ot-shape-complex-arabic-win1256.hh"
index 124a67f..50a5213 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape.hh"
 
 
 /* buffer var allocations */
@@ -160,11 +159,6 @@ static const struct arabic_state_table_entry {
 
 
 static void
-nuke_joiners (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
-             hb_buffer_t *buffer);
-
-static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                       hb_font_t *font,
                       hb_buffer_t *buffer);
@@ -201,32 +195,38 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
    * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
    */
 
-  map->add_gsub_pause (nuke_joiners);
 
-  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
+  map->enable_feature (HB_TAG('s','t','c','h'));
   map->add_gsub_pause (record_stch);
 
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
 
   map->add_gsub_pause (nullptr);
 
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
   {
     bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
-    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
+    map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
     map->add_gsub_pause (nullptr);
   }
 
-  map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
+  /* Normally, Unicode says a ZWNJ means "don't ligate".  In Arabic script
+   * however, it says a ZWJ should also mean "don't ligate".  So we run
+   * the main ligating features as MANUAL_ZWJ. */
+
+  map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK);
+
   if (plan->props.script == HB_SCRIPT_ARABIC)
     map->add_gsub_pause (arabic_fallback_shape);
 
   /* No pause after rclt.  See 98460779bae19e4d64d29461ff154b3527bf8420. */
-  map->add_global_bool_feature (HB_TAG('r','c','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
   map->add_gsub_pause (nullptr);
 
+  /* And undo here. */
+
   /* The spec includes 'cswh'.  Earlier versions of Windows
    * used to enable this by default, but testing suggests
    * that Windows 8 and later do not enable it by default,
@@ -235,23 +235,21 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
    * Note that IranNastaliq uses this feature extensively
    * to fixup broken glyph sequences.  Oh well...
    * Test case: U+0643,U+0640,U+0631. */
-  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
-  map->add_global_bool_feature (HB_TAG('m','s','e','t'));
+  //map->enable_feature (HB_TAG('c','s','w','h'));
+  map->enable_feature (HB_TAG('m','s','e','t'));
 }
 
 #include "hb-ot-shape-complex-arabic-fallback.hh"
 
 struct arabic_shape_plan_t
 {
-  ASSERT_POD ();
-
   /* The "+ 1" in the next array is to accommodate for the "NONE" command,
    * which is not an OpenType feature, but this simplifies the code by not
    * having to do a "if (... < NONE) ..." and just rely on the fact that
    * mask_array[NONE] == 0. */
   hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
 
-  arabic_fallback_plan_t *fallback_plan;
+  hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
 
   unsigned int do_fallback : 1;
   unsigned int has_stch : 1;
@@ -380,19 +378,6 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
   setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
 }
 
-
-static void
-nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
-             hb_font_t *font HB_UNUSED,
-             hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_zwj (&info[i]))
-      _hb_glyph_info_flip_joiners (&info[i]);
-}
-
 static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                       hb_font_t *font,
@@ -404,12 +389,13 @@ arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
     return;
 
 retry:
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan);
+  arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
   if (unlikely (!fallback_plan))
   {
     /* This sucks.  We need a font to build the fallback plan... */
     fallback_plan = arabic_fallback_plan_create (plan, font);
-    if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) {
+    if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
+    {
       arabic_fallback_plan_destroy (fallback_plan);
       goto retry;
     }
@@ -428,7 +414,7 @@ retry:
 
 static void
 record_stch (const hb_ot_shape_plan_t *plan,
-            hb_font_t *font,
+            hb_font_t *font HB_UNUSED,
             hb_buffer_t *buffer)
 {
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
@@ -452,7 +438,7 @@ record_stch (const hb_ot_shape_plan_t *plan,
 }
 
 static void
-apply_stch (const hb_ot_shape_plan_t *plan,
+apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
            hb_buffer_t              *buffer,
            hb_font_t                *font)
 {
@@ -470,9 +456,9 @@ apply_stch (const hb_ot_shape_plan_t *plan,
 
   int sign = font->x_scale < 0 ? -1 : +1;
   unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
-  typedef enum { MEASURE, CUT } step_t;
+  enum { MEASURE, CUT } /* step_t */;
 
-  for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
+  for (unsigned int step = MEASURE; step <= CUT; step = step + 1)
   {
     unsigned int count = buffer->len;
     hb_glyph_info_t *info = buffer->info;
@@ -611,7 +597,7 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
-/* https://unicode.org/reports/tr53/tr53-1.pdf */
+/* http://www.unicode.org/reports/tr53/ */
 
 static hb_codepoint_t
 modifier_combining_marks[] =
@@ -623,6 +609,7 @@ modifier_combining_marks[] =
   0x06E3u, /* ARABIC SMALL LOW SEEN */
   0x06E7u, /* ARABIC SMALL HIGH YEH */
   0x06E8u, /* ARABIC SMALL HIGH NOON */
+  0x08D3u, /* ARABIC SMALL LOW WAW */
   0x08F3u, /* ARABIC SMALL HIGH WAW */
 };
 
@@ -637,7 +624,7 @@ info_is_mcm (const hb_glyph_info_t &info)
 }
 
 static void
-reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
+reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
                      hb_buffer_t              *buffer,
                      unsigned int              start,
                      unsigned int              end)
@@ -714,7 +701,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_arabic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   reorder_marks_arabic,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
diff --git a/src/hb-ot-shape-complex-arabic.hh b/src/hb-ot-shape-complex-arabic.hh
new file mode 100644 (file)
index 0000000..5bf6ff6
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  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.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
+#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+struct arabic_shape_plan_t;
+
+HB_INTERNAL void *
+data_create_arabic (const hb_ot_shape_plan_t *plan);
+
+HB_INTERNAL void
+data_destroy_arabic (void *data);
+
+HB_INTERNAL void
+setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
+                        hb_buffer_t               *buffer,
+                        hb_script_t                script);
+
+#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
index 68a62a1..97923ec 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
@@ -39,7 +39,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
index 7420c5d..e143867 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Hangul shaper */
@@ -56,7 +56,7 @@ collect_features_hangul (hb_ot_shape_planner_t *plan)
   hb_ot_map_builder_t *map = &plan->map;
 
   for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
-    map->add_feature (hangul_features[i], 1, F_NONE);
+    map->add_feature (hangul_features[i]);
 }
 
 static void
@@ -65,13 +65,11 @@ override_features_hangul (hb_ot_shape_planner_t *plan)
   /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
    * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
    * in calt, which is not desirable. */
-  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('c','a','l','t'));
 }
 
 struct hangul_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
 };
 
@@ -128,7 +126,7 @@ is_zero_width_char (hb_font_t *font,
 }
 
 static void
-preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
+preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
                        hb_buffer_t              *buffer,
                        hb_font_t                *font)
 {
@@ -345,13 +343,6 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
        {
          unsigned int s_len = tindex ? 3 : 2;
          buffer->replace_glyphs (1, s_len, decomposed);
-         if (unlikely (!buffer->successful))
-           return;
-
-         /* We decomposed S: apply jamo features to the individual glyphs
-          * that are now in buffer->out_info.
-          */
-         hb_glyph_info_t *info = buffer->out_info;
 
          /* If we decomposed an LV because of a non-combining T following,
           * we want to include this T in the syllable.
@@ -361,6 +352,14 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
             buffer->next_glyph ();
             s_len++;
           }
+
+         if (unlikely (!buffer->successful))
+           return;
+
+         /* We decomposed S: apply jamo features to the individual glyphs
+          * that are now in buffer->out_info.
+          */
+         hb_glyph_info_t *info = buffer->out_info;
           end = start + s_len;
 
          unsigned int i = start;
@@ -368,6 +367,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
          info[i++].hangul_shaping_feature() = VJMO;
          if (i < end)
            info[i++].hangul_shaping_feature() = TJMO;
+
          if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
            buffer->merge_out_clusters (start, end);
          continue;
@@ -424,7 +424,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_hangul,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
index 34cf28b..90c36c0 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 static bool
@@ -70,7 +70,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
 
   bool found = (bool) c->unicode->compose (a, b, ab);
 
-  if (!found && !c->plan->has_mark)
+  if (!found && !c->plan->has_gpos_mark)
   {
       /* Special-case Hebrew presentation forms that are excluded from
        * standard normalization, but wanted for old fonts. */
@@ -154,18 +154,6 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
   return found;
 }
 
-static bool
-disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
-{
-  /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
-   * script.  This matches Uniscribe better, and makes fonts like
-   * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
-   * See:
-   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
-   */
-  return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
-}
-
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
@@ -179,7 +167,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
   nullptr, /* decompose */
   compose_hebrew,
   nullptr, /* setup_masks */
-  disable_otl_hebrew,
+  HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
index 73f9d58..e2ecfb8 100644 (file)
 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-       8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
+       8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-       16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-       4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-       5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-       4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-       16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
-       4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 
-       5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-       5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-       16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-       4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-       8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-       5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
-       4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-       16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 
-       4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 5u, 8u, 5u, 8u, 5u, 7u, 5u, 8u, 
-       5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 
-       8u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-       6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u, 
-       3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-       3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-       3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 
-       5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-       3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-       3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 
-       1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 
-       1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
-       3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-       4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-       4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 
-       10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-       3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-       5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-       1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-       3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-       1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-       3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-       3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 
-       5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 
+       16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
+       4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
+       7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 
+       6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
+       4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
+       4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 
+       5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
+       7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
+       6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 
+       4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, 
+       7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
+       5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
+       4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 
+       4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 
+       5u, 8u, 8u, 8u, 1u, 19u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 
+       3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 
+       3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 
+       5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 
        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-       3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 
-       1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-       1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-       3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, 
-       3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-       3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-       3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 
-       10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
+       3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 
+       3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 
+       1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 
+       3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 
+       3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 
+       3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 
+       10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
+       4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, 
+       3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 
+       1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 
+       1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 10u, 3u, 10u, 4u, 10u, 1u, 16u, 
+       3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 
+       3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 
+       5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 
+       3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
+       5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 
+       3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 
+       1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 
+       3u, 10u, 4u, 8u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 
+       4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 
+       4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, 
+       10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
        5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
-       4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-       3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-       1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-       1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 
-       10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
-       4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
+       4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 
+       1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 
+       3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 1u, 16u, 3u, 13u, 
+       1u, 16u, 4u, 13u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 
        3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 
        0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-       1, 4, 3, 1, 4, 3, 1, 4, 
+       1, 5, 3, 1, 4, 3, 1, 4, 
        3, 1, 4, 3, 1, 5, 1, 1, 
        5, 1, 1, 5, 1, 1, 5, 1, 
-       1, 5, 10, 5, 10, 5, 10, 5, 
-       10, 5, 10, 1, 4, 3, 1, 4, 
-       3, 1, 4, 3, 1, 4, 3, 1, 
-       5, 1, 1, 5, 1, 1, 5, 1, 
-       1, 5, 1, 1, 5, 10, 5, 10, 
-       5, 10, 5, 10, 5, 10, 1, 4, 
-       3, 1, 4, 3, 1, 4, 3, 1, 
-       4, 3, 1, 5, 1, 1, 5, 1, 
+       1, 10, 5, 10, 5, 10, 5, 10, 
+       5, 10, 1, 5, 3, 1, 4, 3, 
+       1, 4, 3, 1, 4, 3, 1, 5, 
+       1, 1, 5, 1, 1, 5, 1, 1, 
+       5, 1, 1, 10, 5, 10, 5, 10, 
+       5, 10, 5, 10, 1, 5, 3, 1, 
+       4, 3, 1, 4, 3, 1, 4, 3, 
        1, 5, 1, 1, 5, 1, 1, 5, 
-       10, 5, 10, 5, 10, 5, 10, 5, 
+       1, 1, 5, 1, 1, 10, 5, 10, 
+       5, 10, 5, 10, 5, 1, 5, 3, 
        1, 4, 3, 1, 4, 3, 1, 4, 
-       3, 1, 4, 3, 1, 5, 1, 1, 
-       5, 1, 1, 5, 1, 1, 5, 1, 
-       1, 5, 10, 5, 10, 5, 10, 5, 
-       10, 5, 10, 10, 4, 4, 3, 4, 
-       3, 1, 4, 3, 1, 4, 3, 1, 
-       1, 5, 1, 1, 5, 1, 1, 5, 
-       1, 1, 5, 1, 1, 1, 19, 15, 
-       15, 14, 16, 15, 15, 14, 16, 15, 
-       15, 14, 16, 15, 15, 14, 16, 15, 
-       15, 14, 6, 6, 6, 1, 1, 1, 
-       6, 8, 8, 7, 6, 8, 7, 6, 
-       8, 7, 6, 8, 7, 6, 8, 7, 
-       15, 15, 16, 16, 16, 16, 15, 15, 
-       16, 16, 16, 16, 15, 15, 16, 16, 
-       16, 16, 15, 15, 16, 16, 16, 16, 
-       15, 15, 15, 15, 14, 16, 15, 15, 
-       14, 16, 15, 15, 14, 16, 15, 15, 
-       14, 16, 15, 15, 14, 6, 6, 6, 
-       1, 1, 1, 6, 8, 8, 7, 6, 
-       8, 7, 6, 8, 7, 6, 8, 7, 
-       6, 8, 7, 15, 15, 16, 16, 16, 
-       16, 15, 15, 16, 16, 16, 16, 15, 
-       15, 16, 16, 16, 16, 15, 15, 16, 
-       16, 16, 16, 5, 15, 15, 14, 16, 
-       15, 15, 14, 16, 15, 15, 14, 16, 
-       15, 15, 14, 16, 15, 15, 14, 6, 
-       6, 6, 1, 1, 1, 6, 8, 8, 
+       3, 1, 5, 1, 1, 5, 1, 1, 
+       5, 1, 1, 5, 1, 1, 10, 5, 
+       10, 5, 10, 5, 10, 5, 10, 10, 
+       4, 1, 19, 11, 8, 7, 16, 11, 
+       8, 7, 16, 11, 8, 7, 16, 11, 
+       8, 7, 16, 11, 8, 7, 6, 6, 
+       6, 1, 1, 1, 6, 8, 6, 8, 
        7, 6, 8, 7, 6, 8, 7, 6, 
-       8, 7, 6, 8, 7, 15, 15, 16, 
-       16, 16, 16, 15, 15, 16, 16, 16, 
-       16, 15, 15, 16, 16, 16, 16, 15, 
-       15, 16, 16, 16, 16, 10, 15, 5, 
-       15, 15, 14, 16, 15, 15, 14, 16, 
-       15, 15, 14, 16, 15, 15, 14, 16, 
-       15, 15, 14, 6, 6, 6, 1, 1, 
-       1, 6, 8, 8, 7, 6, 8, 7, 
+       8, 7, 8, 11, 16, 16, 16, 8, 
+       11, 16, 16, 16, 8, 11, 16, 16, 
+       16, 8, 11, 16, 16, 16, 8, 11, 
+       11, 8, 7, 16, 11, 8, 7, 16, 
+       11, 8, 7, 16, 11, 8, 7, 16, 
+       11, 8, 7, 6, 6, 6, 1, 1, 
+       1, 6, 8, 6, 8, 7, 6, 8, 
+       7, 6, 8, 7, 6, 8, 7, 8, 
+       11, 16, 16, 16, 8, 11, 16, 16, 
+       16, 8, 11, 16, 16, 16, 8, 11, 
+       16, 16, 16, 5, 8, 8, 7, 16, 
+       11, 8, 7, 16, 11, 8, 7, 16, 
+       11, 8, 7, 16, 11, 8, 7, 6, 
+       6, 6, 1, 1, 1, 6, 8, 6, 
+       8, 7, 6, 8, 7, 6, 8, 7, 
+       6, 8, 7, 8, 11, 16, 16, 16, 
+       8, 11, 16, 16, 16, 8, 11, 16, 
+       16, 16, 8, 11, 16, 16, 16, 10, 
+       8, 5, 11, 8, 7, 16, 11, 8, 
+       7, 16, 11, 8, 7, 16, 11, 8, 
+       7, 16, 11, 8, 7, 6, 6, 6, 
+       1, 1, 1, 6, 8, 6, 8, 7, 
        6, 8, 7, 6, 8, 7, 6, 8, 
-       7, 15, 15, 16, 16, 16, 16, 15, 
-       15, 16, 16, 16, 16, 15, 15, 16, 
-       16, 16, 16, 15, 15, 16, 16, 16, 
-       16, 15, 17, 15, 17, 10, 6, 1, 
-       1, 1, 6, 16, 8, 7, 6, 8, 
-       7, 6, 8, 7, 6, 8, 7, 6, 
+       7, 8, 11, 16, 16, 16, 8, 11, 
+       16, 16, 16, 8, 11, 16, 16, 16, 
+       8, 11, 16, 16, 16, 8, 16, 11, 
+       16, 10, 6, 1, 1, 1, 6, 16, 
        8, 6, 6, 1, 1, 1, 6, 16
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-       0, 2, 7, 11, 13, 18, 22, 24, 
-       29, 33, 35, 40, 44, 46, 52, 54, 
-       56, 62, 64, 66, 72, 74, 76, 82, 
-       84, 86, 92, 103, 109, 120, 126, 137, 
-       143, 154, 160, 171, 173, 178, 182, 184, 
-       189, 193, 195, 200, 204, 206, 211, 215, 
-       217, 223, 225, 227, 233, 235, 237, 243, 
-       245, 247, 253, 255, 257, 263, 274, 280, 
-       291, 297, 308, 314, 325, 331, 342, 344, 
-       349, 353, 355, 360, 364, 366, 371, 375, 
-       377, 382, 386, 388, 394, 396, 398, 404, 
-       406, 408, 414, 416, 418, 424, 426, 428, 
-       434, 445, 451, 462, 468, 479, 485, 496, 
-       502, 504, 509, 513, 515, 520, 524, 526, 
-       531, 535, 537, 542, 546, 548, 554, 556, 
-       558, 564, 566, 568, 574, 576, 578, 584, 
-       586, 588, 594, 605, 611, 622, 628, 639, 
-       645, 656, 662, 673, 684, 689, 694, 698, 
-       703, 707, 709, 714, 718, 720, 725, 729, 
-       731, 733, 739, 741, 743, 749, 751, 753, 
-       759, 761, 763, 769, 771, 773, 775, 795, 
-       811, 827, 842, 859, 875, 891, 906, 923, 
-       939, 955, 970, 987, 1003, 1019, 1034, 1051, 
-       1067, 1083, 1098, 1105, 1112, 1119, 1121, 1123, 
-       1125, 1132, 1141, 1150, 1158, 1165, 1174, 1182, 
-       1189, 1198, 1206, 1213, 1222, 1230, 1237, 1246, 
-       1254, 1270, 1286, 1303, 1320, 1337, 1354, 1370, 
-       1386, 1403, 1420, 1437, 1454, 1470, 1486, 1503, 
-       1520, 1537, 1554, 1570, 1586, 1603, 1620, 1637, 
-       1654, 1670, 1686, 1702, 1718, 1733, 1750, 1766, 
-       1782, 1797, 1814, 1830, 1846, 1861, 1878, 1894, 
-       1910, 1925, 1942, 1958, 1974, 1989, 1996, 2003, 
-       2010, 2012, 2014, 2016, 2023, 2032, 2041, 2049, 
-       2056, 2065, 2073, 2080, 2089, 2097, 2104, 2113, 
-       2121, 2128, 2137, 2145, 2161, 2177, 2194, 2211, 
-       2228, 2245, 2261, 2277, 2294, 2311, 2328, 2345, 
-       2361, 2377, 2394, 2411, 2428, 2445, 2461, 2477, 
-       2494, 2511, 2528, 2545, 2551, 2567, 2583, 2598, 
-       2615, 2631, 2647, 2662, 2679, 2695, 2711, 2726, 
-       2743, 2759, 2775, 2790, 2807, 2823, 2839, 2854, 
-       2861, 2868, 2875, 2877, 2879, 2881, 2888, 2897, 
-       2906, 2914, 2921, 2930, 2938, 2945, 2954, 2962, 
-       2969, 2978, 2986, 2993, 3002, 3010, 3026, 3042, 
-       3059, 3076, 3093, 3110, 3126, 3142, 3159, 3176, 
-       3193, 3210, 3226, 3242, 3259, 3276, 3293, 3310, 
-       3326, 3342, 3359, 3376, 3393, 3410, 3421, 3437, 
-       3443, 3459, 3475, 3490, 3507, 3523, 3539, 3554, 
-       3571, 3587, 3603, 3618, 3635, 3651, 3667, 3682, 
-       3699, 3715, 3731, 3746, 3753, 3760, 3767, 3769, 
-       3771, 3773, 3780, 3789, 3798, 3806, 3813, 3822, 
-       3830, 3837, 3846, 3854, 3861, 3870, 3878, 3885, 
-       3894, 3902, 3918, 3934, 3951, 3968, 3985, 4002, 
-       4018, 4034, 4051, 4068, 4085, 4102, 4118, 4134, 
-       4151, 4168, 4185, 4202, 4218, 4234, 4251, 4268, 
-       4285, 4302, 4318, 4336, 4352, 4370, 4381, 4388, 
-       4390, 4392, 4394, 4401, 4418, 4427, 4435, 4442, 
-       4451, 4459, 4466, 4475, 4483, 4490, 4499, 4507, 
-       4514, 4523, 4530, 4537, 4539, 4541, 4543, 4550
+       0, 2, 8, 12, 14, 19, 23, 25, 
+       30, 34, 36, 41, 45, 47, 53, 55, 
+       57, 63, 65, 67, 73, 75, 77, 83, 
+       85, 87, 98, 104, 115, 121, 132, 138, 
+       149, 155, 166, 168, 174, 178, 180, 185, 
+       189, 191, 196, 200, 202, 207, 211, 213, 
+       219, 221, 223, 229, 231, 233, 239, 241, 
+       243, 249, 251, 253, 264, 270, 281, 287, 
+       298, 304, 315, 321, 332, 334, 340, 344, 
+       346, 351, 355, 357, 362, 366, 368, 373, 
+       377, 379, 385, 387, 389, 395, 397, 399, 
+       405, 407, 409, 415, 417, 419, 430, 436, 
+       447, 453, 464, 470, 481, 487, 489, 495, 
+       499, 501, 506, 510, 512, 517, 521, 523, 
+       528, 532, 534, 540, 542, 544, 550, 552, 
+       554, 560, 562, 564, 570, 572, 574, 585, 
+       591, 602, 608, 619, 625, 636, 642, 653, 
+       664, 669, 671, 691, 703, 712, 720, 737, 
+       749, 758, 766, 783, 795, 804, 812, 829, 
+       841, 850, 858, 875, 887, 896, 904, 911, 
+       918, 925, 927, 929, 931, 938, 947, 954, 
+       963, 971, 978, 987, 995, 1002, 1011, 1019, 
+       1026, 1035, 1043, 1052, 1064, 1081, 1098, 1115, 
+       1124, 1136, 1153, 1170, 1187, 1196, 1208, 1225, 
+       1242, 1259, 1268, 1280, 1297, 1314, 1331, 1340, 
+       1352, 1364, 1373, 1381, 1398, 1410, 1419, 1427, 
+       1444, 1456, 1465, 1473, 1490, 1502, 1511, 1519, 
+       1536, 1548, 1557, 1565, 1572, 1579, 1586, 1588, 
+       1590, 1592, 1599, 1608, 1615, 1624, 1632, 1639, 
+       1648, 1656, 1663, 1672, 1680, 1687, 1696, 1704, 
+       1713, 1725, 1742, 1759, 1776, 1785, 1797, 1814, 
+       1831, 1848, 1857, 1869, 1886, 1903, 1920, 1929, 
+       1941, 1958, 1975, 1992, 1998, 2007, 2016, 2024, 
+       2041, 2053, 2062, 2070, 2087, 2099, 2108, 2116, 
+       2133, 2145, 2154, 2162, 2179, 2191, 2200, 2208, 
+       2215, 2222, 2229, 2231, 2233, 2235, 2242, 2251, 
+       2258, 2267, 2275, 2282, 2291, 2299, 2306, 2315, 
+       2323, 2330, 2339, 2347, 2356, 2368, 2385, 2402, 
+       2419, 2428, 2440, 2457, 2474, 2491, 2500, 2512, 
+       2529, 2546, 2563, 2572, 2584, 2601, 2618, 2635, 
+       2646, 2655, 2661, 2673, 2682, 2690, 2707, 2719, 
+       2728, 2736, 2753, 2765, 2774, 2782, 2799, 2811, 
+       2820, 2828, 2845, 2857, 2866, 2874, 2881, 2888, 
+       2895, 2897, 2899, 2901, 2908, 2917, 2924, 2933, 
+       2941, 2948, 2957, 2965, 2972, 2981, 2989, 2996, 
+       3005, 3013, 3022, 3034, 3051, 3068, 3085, 3094, 
+       3106, 3123, 3140, 3157, 3166, 3178, 3195, 3212, 
+       3229, 3238, 3250, 3267, 3284, 3301, 3310, 3327, 
+       3339, 3356, 3367, 3374, 3376, 3378, 3380, 3387, 
+       3404, 3413, 3420, 3427, 3429, 3431, 3433, 3440
 };
 
 static const short _indic_syllable_machine_indicies[] = {
-       1, 0, 2, 2, 3, 1, 0, 4, 
-       4, 3, 0, 3, 0, 5, 5, 6, 
-       1, 0, 7, 7, 6, 0, 6, 0, 
-       8, 8, 9, 1, 0, 10, 10, 9, 
-       0, 9, 0, 11, 11, 12, 1, 0, 
-       13, 13, 12, 0, 12, 0, 14, 0, 
-       0, 0, 1, 0, 15, 0, 16, 0, 
-       17, 11, 11, 12, 1, 0, 18, 0, 
-       19, 0, 20, 8, 8, 9, 1, 0, 
-       21, 0, 22, 0, 23, 5, 5, 6, 
-       1, 0, 24, 0, 25, 0, 26, 2, 
-       2, 3, 1, 0, 26, 2, 2, 3, 
-       1, 0, 0, 0, 0, 27, 0, 28, 
-       2, 2, 3, 1, 0, 28, 2, 2, 
-       3, 1, 0, 0, 0, 0, 29, 0, 
-       30, 2, 2, 3, 1, 0, 30, 2, 
-       2, 3, 1, 0, 0, 0, 0, 31, 
-       0, 32, 2, 2, 3, 1, 0, 32, 
-       2, 2, 3, 1, 0, 0, 0, 0, 
-       33, 0, 34, 2, 2, 3, 1, 0, 
-       34, 2, 2, 3, 1, 0, 0, 0, 
-       0, 35, 0, 37, 36, 38, 38, 39, 
-       37, 36, 40, 40, 39, 36, 39, 36, 
-       41, 41, 42, 37, 36, 43, 43, 42, 
-       36, 42, 36, 44, 44, 45, 37, 36, 
-       46, 46, 45, 36, 45, 36, 47, 47, 
-       48, 37, 36, 49, 49, 48, 36, 48, 
-       36, 50, 36, 36, 36, 37, 36, 51, 
-       36, 52, 36, 53, 47, 47, 48, 37, 
-       36, 54, 36, 55, 36, 56, 44, 44, 
-       45, 37, 36, 57, 36, 58, 36, 59, 
-       41, 41, 42, 37, 36, 60, 36, 61, 
-       36, 62, 38, 38, 39, 37, 36, 62, 
-       38, 38, 39, 37, 36, 36, 36, 36, 
-       63, 36, 64, 38, 38, 39, 37, 36, 
-       64, 38, 38, 39, 37, 36, 36, 36, 
-       36, 65, 36, 66, 38, 38, 39, 37, 
-       36, 66, 38, 38, 39, 37, 36, 36, 
-       36, 36, 67, 36, 68, 38, 38, 39, 
-       37, 36, 68, 38, 38, 39, 37, 36, 
-       36, 36, 36, 69, 36, 70, 38, 38, 
-       39, 37, 36, 70, 38, 38, 39, 37, 
-       36, 36, 36, 36, 71, 36, 73, 72, 
-       74, 74, 75, 73, 72, 77, 77, 75, 
-       76, 75, 76, 78, 78, 79, 73, 72, 
-       80, 80, 79, 72, 79, 72, 81, 81, 
-       82, 73, 72, 83, 83, 82, 72, 82, 
-       72, 84, 84, 85, 73, 72, 86, 86, 
-       85, 72, 85, 72, 87, 72, 72, 72, 
-       73, 72, 88, 72, 89, 72, 90, 84, 
-       84, 85, 73, 72, 91, 72, 92, 72, 
-       93, 81, 81, 82, 73, 72, 94, 72, 
-       95, 72, 96, 78, 78, 79, 73, 72, 
-       97, 72, 98, 72, 99, 74, 74, 75, 
-       73, 72, 99, 74, 74, 75, 73, 72, 
-       72, 72, 72, 100, 72, 101, 74, 74, 
-       75, 73, 72, 101, 74, 74, 75, 73, 
-       72, 72, 72, 72, 102, 72, 103, 74, 
-       74, 75, 73, 72, 103, 74, 74, 75, 
-       73, 72, 72, 72, 72, 104, 72, 105, 
-       74, 74, 75, 73, 72, 105, 74, 74, 
-       75, 73, 72, 72, 72, 72, 106, 72, 
-       107, 74, 74, 75, 73, 72, 109, 108, 
-       110, 110, 111, 109, 108, 112, 112, 111, 
-       108, 111, 108, 113, 113, 114, 109, 108, 
-       115, 115, 114, 108, 114, 108, 116, 116, 
-       117, 109, 108, 118, 118, 117, 108, 117, 
-       108, 119, 119, 120, 109, 108, 121, 121, 
-       120, 108, 120, 108, 122, 108, 108, 108, 
-       109, 108, 123, 108, 124, 108, 125, 119, 
-       119, 120, 109, 108, 126, 108, 127, 108, 
-       128, 116, 116, 117, 109, 108, 129, 108, 
-       130, 108, 131, 113, 113, 114, 109, 108, 
-       132, 108, 133, 108, 134, 110, 110, 111, 
-       109, 108, 134, 110, 110, 111, 109, 108, 
-       108, 108, 108, 135, 108, 136, 110, 110, 
-       111, 109, 108, 136, 110, 110, 111, 109, 
-       108, 108, 108, 108, 137, 108, 138, 110, 
-       110, 111, 109, 108, 138, 110, 110, 111, 
-       109, 108, 108, 108, 108, 139, 108, 140, 
-       110, 110, 111, 109, 108, 140, 110, 110, 
-       111, 109, 108, 108, 108, 108, 141, 108, 
-       142, 110, 110, 111, 109, 108, 142, 110, 
-       110, 111, 109, 108, 108, 108, 108, 143, 
-       108, 107, 74, 74, 75, 73, 72, 72, 
-       72, 72, 144, 72, 77, 77, 75, 1, 
-       0, 145, 145, 146, 1, 0, 4, 4, 
-       146, 0, 147, 147, 148, 149, 0, 150, 
-       150, 148, 0, 148, 0, 151, 151, 152, 
-       149, 0, 153, 153, 152, 0, 152, 0, 
-       154, 154, 155, 149, 0, 156, 156, 155, 
-       0, 155, 0, 149, 0, 157, 0, 0, 
-       0, 149, 0, 158, 0, 159, 0, 160, 
-       154, 154, 155, 149, 0, 161, 0, 162, 
-       0, 163, 151, 151, 152, 149, 0, 164, 
-       0, 165, 0, 166, 147, 147, 148, 149, 
-       0, 167, 0, 168, 0, 170, 169, 172, 
-       173, 174, 175, 176, 177, 75, 73, 171, 
-       178, 179, 179, 144, 171, 180, 181, 182, 
-       183, 184, 171, 186, 187, 188, 189, 3, 
-       1, 185, 190, 185, 185, 35, 185, 185, 
-       185, 191, 185, 192, 187, 193, 193, 3, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       185, 191, 185, 187, 193, 193, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 194, 185, 185, 185, 16, 195, 
-       185, 1, 185, 190, 185, 185, 185, 185, 
-       185, 194, 185, 196, 197, 198, 199, 3, 
-       1, 185, 190, 185, 185, 33, 185, 185, 
-       185, 191, 185, 200, 197, 201, 201, 3, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       185, 191, 185, 197, 201, 201, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 202, 185, 185, 185, 16, 203, 
-       185, 1, 185, 190, 185, 185, 185, 185, 
-       185, 202, 185, 204, 205, 206, 207, 3, 
-       1, 185, 190, 185, 185, 31, 185, 185, 
-       185, 191, 185, 208, 205, 209, 209, 3, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       185, 191, 185, 205, 209, 209, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 210, 185, 185, 185, 16, 211, 
-       185, 1, 185, 190, 185, 185, 185, 185, 
-       185, 210, 185, 212, 213, 214, 215, 3, 
-       1, 185, 190, 185, 185, 29, 185, 185, 
-       185, 191, 185, 216, 213, 217, 217, 3, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       185, 191, 185, 213, 217, 217, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 218, 185, 185, 185, 16, 219, 
-       185, 1, 185, 190, 185, 185, 185, 185, 
-       185, 218, 185, 220, 221, 222, 223, 3, 
-       1, 185, 190, 185, 185, 27, 185, 185, 
-       185, 191, 185, 224, 221, 225, 225, 3, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       185, 191, 185, 221, 225, 225, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 16, 226, 185, 1, 185, 190, 
-       185, 227, 227, 185, 1, 185, 190, 185, 
-       228, 185, 185, 229, 185, 190, 185, 190, 
-       185, 230, 185, 231, 185, 228, 185, 185, 
-       185, 185, 190, 185, 16, 185, 232, 232, 
-       3, 1, 185, 190, 185, 233, 25, 234, 
-       235, 6, 1, 185, 190, 185, 25, 234, 
-       235, 6, 1, 185, 190, 185, 234, 234, 
-       6, 1, 185, 190, 185, 236, 22, 237, 
-       238, 9, 1, 185, 190, 185, 22, 237, 
-       238, 9, 1, 185, 190, 185, 237, 237, 
-       9, 1, 185, 190, 185, 239, 19, 240, 
-       241, 12, 1, 185, 190, 185, 19, 240, 
-       241, 12, 1, 185, 190, 185, 240, 240, 
-       12, 1, 185, 190, 185, 242, 16, 227, 
-       243, 185, 1, 185, 190, 185, 16, 227, 
-       243, 185, 1, 185, 190, 185, 227, 244, 
-       185, 1, 185, 190, 185, 16, 185, 227, 
-       227, 185, 1, 185, 190, 185, 221, 225, 
-       225, 3, 1, 185, 190, 185, 220, 221, 
-       225, 225, 3, 1, 185, 190, 185, 185, 
-       185, 185, 185, 185, 191, 185, 220, 221, 
-       222, 225, 3, 1, 185, 190, 185, 185, 
-       27, 185, 185, 185, 191, 185, 218, 185, 
-       245, 185, 232, 232, 3, 1, 185, 190, 
-       185, 185, 185, 185, 185, 218, 185, 218, 
-       185, 185, 185, 227, 227, 185, 1, 185, 
-       190, 185, 185, 185, 185, 185, 218, 185, 
-       218, 185, 185, 185, 227, 246, 185, 1, 
-       185, 190, 185, 185, 185, 185, 185, 218, 
-       185, 218, 185, 245, 185, 227, 227, 185, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       218, 185, 212, 213, 217, 217, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 212, 213, 214, 217, 3, 1, 
-       185, 190, 185, 185, 29, 185, 185, 185, 
-       191, 185, 210, 185, 247, 185, 232, 232, 
-       3, 1, 185, 190, 185, 185, 185, 185, 
-       185, 210, 185, 210, 185, 185, 185, 227, 
-       227, 185, 1, 185, 190, 185, 185, 185, 
-       185, 185, 210, 185, 210, 185, 185, 185, 
-       227, 248, 185, 1, 185, 190, 185, 185, 
-       185, 185, 185, 210, 185, 210, 185, 247, 
-       185, 227, 227, 185, 1, 185, 190, 185, 
-       185, 185, 185, 185, 210, 185, 204, 205, 
-       209, 209, 3, 1, 185, 190, 185, 185, 
-       185, 185, 185, 185, 191, 185, 204, 205, 
-       206, 209, 3, 1, 185, 190, 185, 185, 
-       31, 185, 185, 185, 191, 185, 202, 185, 
-       249, 185, 232, 232, 3, 1, 185, 190, 
-       185, 185, 185, 185, 185, 202, 185, 202, 
-       185, 185, 185, 227, 227, 185, 1, 185, 
-       190, 185, 185, 185, 185, 185, 202, 185, 
-       202, 185, 185, 185, 227, 250, 185, 1, 
-       185, 190, 185, 185, 185, 185, 185, 202, 
-       185, 202, 185, 249, 185, 227, 227, 185, 
-       1, 185, 190, 185, 185, 185, 185, 185, 
-       202, 185, 196, 197, 201, 201, 3, 1, 
-       185, 190, 185, 185, 185, 185, 185, 185, 
-       191, 185, 196, 197, 198, 201, 3, 1, 
-       185, 190, 185, 185, 33, 185, 185, 185, 
-       191, 185, 194, 185, 251, 185, 232, 232, 
-       3, 1, 185, 190, 185, 185, 185, 185, 
-       185, 194, 185, 194, 185, 185, 185, 227, 
-       227, 185, 1, 185, 190, 185, 185, 185, 
-       185, 185, 194, 185, 194, 185, 185, 185, 
-       227, 252, 185, 1, 185, 190, 185, 185, 
-       185, 185, 185, 194, 185, 194, 185, 251, 
-       185, 227, 227, 185, 1, 185, 190, 185, 
-       185, 185, 185, 185, 194, 185, 186, 187, 
-       193, 193, 3, 1, 185, 190, 185, 185, 
-       185, 185, 185, 185, 191, 185, 186, 187, 
-       188, 193, 3, 1, 185, 190, 185, 185, 
-       35, 185, 185, 185, 191, 185, 254, 255, 
-       256, 257, 39, 37, 253, 258, 253, 253, 
-       71, 253, 253, 253, 259, 253, 260, 255, 
-       261, 257, 39, 37, 253, 258, 253, 253, 
-       253, 253, 253, 253, 259, 253, 255, 261, 
-       257, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 262, 253, 253, 
-       253, 52, 263, 253, 37, 253, 258, 253, 
-       253, 253, 253, 253, 262, 253, 264, 265, 
-       266, 267, 39, 37, 253, 258, 253, 253, 
-       69, 253, 253, 253, 259, 253, 268, 265, 
-       269, 269, 39, 37, 253, 258, 253, 253, 
-       253, 253, 253, 253, 259, 253, 265, 269, 
-       269, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 270, 253, 253, 
-       253, 52, 271, 253, 37, 253, 258, 253, 
-       253, 253, 253, 253, 270, 253, 272, 273, 
-       274, 275, 39, 37, 253, 258, 253, 253, 
-       67, 253, 253, 253, 259, 253, 276, 273, 
-       277, 277, 39, 37, 253, 258, 253, 253, 
-       253, 253, 253, 253, 259, 253, 273, 277, 
-       277, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 278, 253, 253, 
-       253, 52, 279, 253, 37, 253, 258, 253, 
-       253, 253, 253, 253, 278, 253, 280, 281, 
-       282, 283, 39, 37, 253, 258, 253, 253, 
-       65, 253, 253, 253, 259, 253, 284, 281, 
-       285, 285, 39, 37, 253, 258, 253, 253, 
-       253, 253, 253, 253, 259, 253, 281, 285, 
-       285, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 286, 253, 253, 
-       253, 52, 287, 253, 37, 253, 258, 253, 
-       253, 253, 253, 253, 286, 253, 288, 289, 
-       290, 291, 39, 37, 253, 258, 253, 253, 
-       63, 253, 253, 253, 259, 253, 292, 289, 
-       293, 293, 39, 37, 253, 258, 253, 253, 
-       253, 253, 253, 253, 259, 253, 289, 293, 
-       293, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 52, 294, 253, 
-       37, 253, 258, 253, 295, 295, 253, 37, 
-       253, 258, 253, 296, 253, 253, 297, 253, 
-       258, 253, 258, 253, 298, 253, 299, 253, 
-       296, 253, 253, 253, 253, 258, 253, 52, 
-       253, 300, 300, 39, 37, 253, 258, 253, 
-       301, 61, 302, 303, 42, 37, 253, 258, 
-       253, 61, 302, 303, 42, 37, 253, 258, 
-       253, 302, 302, 42, 37, 253, 258, 253, 
-       304, 58, 305, 306, 45, 37, 253, 258, 
-       253, 58, 305, 306, 45, 37, 253, 258, 
-       253, 305, 305, 45, 37, 253, 258, 253, 
-       307, 55, 308, 309, 48, 37, 253, 258, 
-       253, 55, 308, 309, 48, 37, 253, 258, 
-       253, 308, 308, 48, 37, 253, 258, 253, 
-       310, 52, 295, 311, 253, 37, 253, 258, 
-       253, 52, 295, 311, 253, 37, 253, 258, 
-       253, 295, 312, 253, 37, 253, 258, 253, 
-       52, 253, 295, 295, 253, 37, 253, 258, 
-       253, 289, 293, 293, 39, 37, 253, 258, 
-       253, 288, 289, 293, 293, 39, 37, 253, 
-       258, 253, 253, 253, 253, 253, 253, 259, 
-       253, 288, 289, 290, 293, 39, 37, 253, 
-       258, 253, 253, 63, 253, 253, 253, 259, 
-       253, 286, 253, 313, 253, 300, 300, 39, 
-       37, 253, 258, 253, 253, 253, 253, 253, 
-       286, 253, 286, 253, 253, 253, 295, 295, 
-       253, 37, 253, 258, 253, 253, 253, 253, 
-       253, 286, 253, 286, 253, 253, 253, 295, 
-       314, 253, 37, 253, 258, 253, 253, 253, 
-       253, 253, 286, 253, 286, 253, 313, 253, 
-       295, 295, 253, 37, 253, 258, 253, 253, 
-       253, 253, 253, 286, 253, 280, 281, 285, 
-       285, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 280, 281, 282, 
-       285, 39, 37, 253, 258, 253, 253, 65, 
-       253, 253, 253, 259, 253, 278, 253, 315, 
-       253, 300, 300, 39, 37, 253, 258, 253, 
-       253, 253, 253, 253, 278, 253, 278, 253, 
-       253, 253, 295, 295, 253, 37, 253, 258, 
-       253, 253, 253, 253, 253, 278, 253, 278, 
-       253, 253, 253, 295, 316, 253, 37, 253, 
-       258, 253, 253, 253, 253, 253, 278, 253, 
-       278, 253, 315, 253, 295, 295, 253, 37, 
-       253, 258, 253, 253, 253, 253, 253, 278, 
-       253, 272, 273, 277, 277, 39, 37, 253, 
-       258, 253, 253, 253, 253, 253, 253, 259, 
-       253, 272, 273, 274, 277, 39, 37, 253, 
-       258, 253, 253, 67, 253, 253, 253, 259, 
-       253, 270, 253, 317, 253, 300, 300, 39, 
-       37, 253, 258, 253, 253, 253, 253, 253, 
-       270, 253, 270, 253, 253, 253, 295, 295, 
-       253, 37, 253, 258, 253, 253, 253, 253, 
-       253, 270, 253, 270, 253, 253, 253, 295, 
-       318, 253, 37, 253, 258, 253, 253, 253, 
-       253, 253, 270, 253, 270, 253, 317, 253, 
-       295, 295, 253, 37, 253, 258, 253, 253, 
-       253, 253, 253, 270, 253, 264, 265, 269, 
-       269, 39, 37, 253, 258, 253, 253, 253, 
-       253, 253, 253, 259, 253, 264, 265, 266, 
-       269, 39, 37, 253, 258, 253, 253, 69, 
-       253, 253, 253, 259, 253, 262, 253, 319, 
-       253, 300, 300, 39, 37, 253, 258, 253, 
-       253, 253, 253, 253, 262, 253, 262, 253, 
-       253, 253, 295, 295, 253, 37, 253, 258, 
-       253, 253, 253, 253, 253, 262, 253, 262, 
-       253, 253, 253, 295, 320, 253, 37, 253, 
-       258, 253, 253, 253, 253, 253, 262, 253, 
-       262, 253, 319, 253, 295, 295, 253, 37, 
-       253, 258, 253, 253, 253, 253, 253, 262, 
-       253, 70, 38, 38, 39, 37, 253, 254, 
-       255, 261, 257, 39, 37, 253, 258, 253, 
-       253, 253, 253, 253, 253, 259, 253, 322, 
-       175, 323, 323, 75, 73, 321, 178, 321, 
-       321, 321, 321, 321, 321, 182, 321, 175, 
-       323, 323, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 324, 321, 
-       321, 321, 89, 325, 321, 73, 321, 178, 
-       321, 321, 321, 321, 321, 324, 321, 326, 
-       327, 328, 329, 75, 73, 321, 178, 321, 
-       321, 106, 321, 321, 321, 182, 321, 330, 
-       327, 331, 331, 75, 73, 321, 178, 321, 
-       321, 321, 321, 321, 321, 182, 321, 327, 
-       331, 331, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 332, 321, 
-       321, 321, 89, 333, 321, 73, 321, 178, 
-       321, 321, 321, 321, 321, 332, 321, 334, 
-       335, 336, 337, 75, 73, 321, 178, 321, 
-       321, 104, 321, 321, 321, 182, 321, 338, 
-       335, 339, 339, 75, 73, 321, 178, 321, 
-       321, 321, 321, 321, 321, 182, 321, 335, 
-       339, 339, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 340, 321, 
-       321, 321, 89, 341, 321, 73, 321, 178, 
-       321, 321, 321, 321, 321, 340, 321, 342, 
-       343, 344, 345, 75, 73, 321, 178, 321, 
-       321, 102, 321, 321, 321, 182, 321, 346, 
-       343, 347, 347, 75, 73, 321, 178, 321, 
-       321, 321, 321, 321, 321, 182, 321, 343, 
-       347, 347, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 348, 321, 
-       321, 321, 89, 349, 321, 73, 321, 178, 
-       321, 321, 321, 321, 321, 348, 321, 350, 
-       351, 352, 353, 75, 73, 321, 178, 321, 
-       321, 100, 321, 321, 321, 182, 321, 354, 
-       351, 355, 355, 75, 73, 321, 178, 321, 
-       321, 321, 321, 321, 321, 182, 321, 351, 
-       355, 355, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 89, 356, 
-       321, 73, 321, 178, 321, 357, 357, 321, 
-       73, 321, 178, 321, 358, 321, 321, 359, 
-       321, 178, 321, 178, 321, 360, 321, 361, 
-       321, 358, 321, 321, 321, 321, 178, 321, 
-       89, 321, 362, 362, 75, 73, 321, 178, 
-       321, 363, 98, 364, 365, 79, 73, 321, 
-       178, 321, 98, 364, 365, 79, 73, 321, 
-       178, 321, 364, 364, 79, 73, 321, 178, 
-       321, 366, 95, 367, 368, 82, 73, 321, 
-       178, 321, 95, 367, 368, 82, 73, 321, 
-       178, 321, 367, 367, 82, 73, 321, 178, 
-       321, 369, 92, 370, 371, 85, 73, 321, 
-       178, 321, 92, 370, 371, 85, 73, 321, 
-       178, 321, 370, 370, 85, 73, 321, 178, 
-       321, 372, 89, 357, 373, 321, 73, 321, 
-       178, 321, 89, 357, 373, 321, 73, 321, 
-       178, 321, 357, 374, 321, 73, 321, 178, 
-       321, 89, 321, 357, 357, 321, 73, 321, 
-       178, 321, 351, 355, 355, 75, 73, 321, 
-       178, 321, 350, 351, 355, 355, 75, 73, 
-       321, 178, 321, 321, 321, 321, 321, 321, 
-       182, 321, 350, 351, 352, 355, 75, 73, 
-       321, 178, 321, 321, 100, 321, 321, 321, 
-       182, 321, 348, 321, 375, 321, 362, 362, 
-       75, 73, 321, 178, 321, 321, 321, 321, 
-       321, 348, 321, 348, 321, 321, 321, 357, 
-       357, 321, 73, 321, 178, 321, 321, 321, 
-       321, 321, 348, 321, 348, 321, 321, 321, 
-       357, 376, 321, 73, 321, 178, 321, 321, 
-       321, 321, 321, 348, 321, 348, 321, 375, 
-       321, 357, 357, 321, 73, 321, 178, 321, 
-       321, 321, 321, 321, 348, 321, 342, 343, 
-       347, 347, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 342, 343, 
-       344, 347, 75, 73, 321, 178, 321, 321, 
-       102, 321, 321, 321, 182, 321, 340, 321, 
-       377, 321, 362, 362, 75, 73, 321, 178, 
-       321, 321, 321, 321, 321, 340, 321, 340, 
-       321, 321, 321, 357, 357, 321, 73, 321, 
-       178, 321, 321, 321, 321, 321, 340, 321, 
-       340, 321, 321, 321, 357, 378, 321, 73, 
-       321, 178, 321, 321, 321, 321, 321, 340, 
-       321, 340, 321, 377, 321, 357, 357, 321, 
-       73, 321, 178, 321, 321, 321, 321, 321, 
-       340, 321, 334, 335, 339, 339, 75, 73, 
-       321, 178, 321, 321, 321, 321, 321, 321, 
-       182, 321, 334, 335, 336, 339, 75, 73, 
-       321, 178, 321, 321, 104, 321, 321, 321, 
-       182, 321, 332, 321, 379, 321, 362, 362, 
-       75, 73, 321, 178, 321, 321, 321, 321, 
-       321, 332, 321, 332, 321, 321, 321, 357, 
-       357, 321, 73, 321, 178, 321, 321, 321, 
-       321, 321, 332, 321, 332, 321, 321, 321, 
-       357, 380, 321, 73, 321, 178, 321, 321, 
-       321, 321, 321, 332, 321, 332, 321, 379, 
-       321, 357, 357, 321, 73, 321, 178, 321, 
-       321, 321, 321, 321, 332, 321, 326, 327, 
-       331, 331, 75, 73, 321, 178, 321, 321, 
-       321, 321, 321, 321, 182, 321, 326, 327, 
-       328, 331, 75, 73, 321, 178, 321, 321, 
-       106, 321, 321, 321, 182, 321, 324, 321, 
-       381, 321, 362, 362, 75, 73, 321, 178, 
-       321, 321, 321, 321, 321, 324, 321, 324, 
-       321, 321, 321, 357, 357, 321, 73, 321, 
-       178, 321, 321, 321, 321, 321, 324, 321, 
-       324, 321, 321, 321, 357, 382, 321, 73, 
-       321, 178, 321, 321, 321, 321, 321, 324, 
-       321, 324, 321, 381, 321, 357, 357, 321, 
-       73, 321, 178, 321, 321, 321, 321, 321, 
-       324, 321, 107, 74, 74, 75, 73, 383, 
-       383, 383, 383, 144, 383, 174, 175, 323, 
-       323, 75, 73, 321, 178, 321, 321, 321, 
-       321, 321, 321, 182, 321, 107, 74, 74, 
-       75, 73, 383, 385, 386, 387, 388, 111, 
-       109, 384, 389, 384, 384, 143, 384, 384, 
-       384, 390, 384, 391, 386, 388, 388, 111, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       384, 390, 384, 386, 388, 388, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 392, 384, 384, 384, 124, 393, 
-       384, 109, 384, 389, 384, 384, 384, 384, 
-       384, 392, 384, 394, 395, 396, 397, 111, 
-       109, 384, 389, 384, 384, 141, 384, 384, 
-       384, 390, 384, 398, 395, 399, 399, 111, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       384, 390, 384, 395, 399, 399, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 400, 384, 384, 384, 124, 401, 
-       384, 109, 384, 389, 384, 384, 384, 384, 
-       384, 400, 384, 402, 403, 404, 405, 111, 
-       109, 384, 389, 384, 384, 139, 384, 384, 
-       384, 390, 384, 406, 403, 407, 407, 111, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       384, 390, 384, 403, 407, 407, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 408, 384, 384, 384, 124, 409, 
-       384, 109, 384, 389, 384, 384, 384, 384, 
-       384, 408, 384, 410, 411, 412, 413, 111, 
-       109, 384, 389, 384, 384, 137, 384, 384, 
-       384, 390, 384, 414, 411, 415, 415, 111, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       384, 390, 384, 411, 415, 415, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 416, 384, 384, 384, 124, 417, 
-       384, 109, 384, 389, 384, 384, 384, 384, 
-       384, 416, 384, 418, 419, 420, 421, 111, 
-       109, 384, 389, 384, 384, 135, 384, 384, 
-       384, 390, 384, 422, 419, 423, 423, 111, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       384, 390, 384, 419, 423, 423, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 124, 424, 384, 109, 384, 389, 
-       384, 425, 425, 384, 109, 384, 389, 384, 
-       426, 384, 384, 427, 384, 389, 384, 389, 
-       384, 428, 384, 429, 384, 426, 384, 384, 
-       384, 384, 389, 384, 124, 384, 430, 430, 
-       111, 109, 384, 389, 384, 431, 133, 432, 
-       433, 114, 109, 384, 389, 384, 133, 432, 
-       433, 114, 109, 384, 389, 384, 432, 432, 
-       114, 109, 384, 389, 384, 434, 130, 435, 
-       436, 117, 109, 384, 389, 384, 130, 435, 
-       436, 117, 109, 384, 389, 384, 435, 435, 
-       117, 109, 384, 389, 384, 437, 127, 438, 
-       439, 120, 109, 384, 389, 384, 127, 438, 
-       439, 120, 109, 384, 389, 384, 438, 438, 
-       120, 109, 384, 389, 384, 440, 124, 425, 
-       441, 384, 109, 384, 389, 384, 124, 425, 
-       441, 384, 109, 384, 389, 384, 425, 442, 
-       384, 109, 384, 389, 384, 124, 384, 425, 
-       425, 384, 109, 384, 389, 384, 419, 423, 
-       423, 111, 109, 384, 389, 384, 418, 419, 
-       423, 423, 111, 109, 384, 389, 384, 384, 
-       384, 384, 384, 384, 390, 384, 418, 419, 
-       420, 423, 111, 109, 384, 389, 384, 384, 
-       135, 384, 384, 384, 390, 384, 416, 384, 
-       443, 384, 430, 430, 111, 109, 384, 389, 
-       384, 384, 384, 384, 384, 416, 384, 416, 
-       384, 384, 384, 425, 425, 384, 109, 384, 
-       389, 384, 384, 384, 384, 384, 416, 384, 
-       416, 384, 384, 384, 425, 444, 384, 109, 
-       384, 389, 384, 384, 384, 384, 384, 416, 
-       384, 416, 384, 443, 384, 425, 425, 384, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       416, 384, 410, 411, 415, 415, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 410, 411, 412, 415, 111, 109, 
-       384, 389, 384, 384, 137, 384, 384, 384, 
-       390, 384, 408, 384, 445, 384, 430, 430, 
-       111, 109, 384, 389, 384, 384, 384, 384, 
-       384, 408, 384, 408, 384, 384, 384, 425, 
-       425, 384, 109, 384, 389, 384, 384, 384, 
-       384, 384, 408, 384, 408, 384, 384, 384, 
-       425, 446, 384, 109, 384, 389, 384, 384, 
-       384, 384, 384, 408, 384, 408, 384, 445, 
-       384, 425, 425, 384, 109, 384, 389, 384, 
-       384, 384, 384, 384, 408, 384, 402, 403, 
-       407, 407, 111, 109, 384, 389, 384, 384, 
-       384, 384, 384, 384, 390, 384, 402, 403, 
-       404, 407, 111, 109, 384, 389, 384, 384, 
-       139, 384, 384, 384, 390, 384, 400, 384, 
-       447, 384, 430, 430, 111, 109, 384, 389, 
-       384, 384, 384, 384, 384, 400, 384, 400, 
-       384, 384, 384, 425, 425, 384, 109, 384, 
-       389, 384, 384, 384, 384, 384, 400, 384, 
-       400, 384, 384, 384, 425, 448, 384, 109, 
-       384, 389, 384, 384, 384, 384, 384, 400, 
-       384, 400, 384, 447, 384, 425, 425, 384, 
-       109, 384, 389, 384, 384, 384, 384, 384, 
-       400, 384, 394, 395, 399, 399, 111, 109, 
-       384, 389, 384, 384, 384, 384, 384, 384, 
-       390, 384, 394, 395, 396, 399, 111, 109, 
-       384, 389, 384, 384, 141, 384, 384, 384, 
-       390, 384, 392, 384, 449, 384, 430, 430, 
-       111, 109, 384, 389, 384, 384, 384, 384, 
-       384, 392, 384, 392, 384, 384, 384, 425, 
-       425, 384, 109, 384, 389, 384, 384, 384, 
-       384, 384, 392, 384, 392, 384, 384, 384, 
-       425, 450, 384, 109, 384, 389, 384, 384, 
-       384, 384, 384, 392, 384, 392, 384, 449, 
-       384, 425, 425, 384, 109, 384, 389, 384, 
-       384, 384, 384, 384, 392, 384, 385, 386, 
-       388, 388, 111, 109, 384, 389, 384, 384, 
-       384, 384, 384, 384, 390, 384, 172, 173, 
-       174, 175, 451, 323, 75, 73, 321, 178, 
-       179, 179, 144, 321, 321, 172, 182, 321, 
-       186, 452, 188, 189, 3, 1, 185, 190, 
-       185, 185, 35, 185, 185, 185, 191, 185, 
-       194, 173, 174, 175, 453, 454, 75, 149, 
-       185, 455, 185, 179, 144, 185, 185, 194, 
-       182, 185, 107, 456, 456, 75, 149, 185, 
-       190, 185, 185, 144, 185, 457, 185, 185, 
-       458, 185, 455, 185, 455, 185, 459, 185, 
-       231, 185, 457, 185, 185, 185, 185, 455, 
-       185, 194, 185, 251, 107, 460, 460, 146, 
-       149, 185, 190, 185, 185, 185, 185, 185, 
-       194, 185, 461, 168, 462, 463, 148, 149, 
-       185, 455, 185, 168, 462, 463, 148, 149, 
-       185, 455, 185, 462, 462, 148, 149, 185, 
-       455, 185, 464, 165, 465, 466, 152, 149, 
-       185, 455, 185, 165, 465, 466, 152, 149, 
-       185, 455, 185, 465, 465, 152, 149, 185, 
-       455, 185, 467, 162, 468, 469, 155, 149, 
-       185, 455, 185, 162, 468, 469, 155, 149, 
-       185, 455, 185, 468, 468, 155, 149, 185, 
-       455, 185, 470, 159, 471, 472, 185, 149, 
-       185, 455, 185, 159, 471, 472, 185, 149, 
-       185, 455, 185, 471, 471, 185, 149, 185, 
-       455, 185, 474, 473, 475, 475, 473, 170, 
-       473, 476, 473, 475, 475, 473, 170, 473, 
-       476, 473, 477, 473, 473, 478, 473, 476, 
-       473, 476, 473, 479, 473, 480, 473, 477, 
-       473, 473, 473, 473, 476, 473, 172, 383, 
-       383, 383, 383, 383, 383, 383, 383, 383, 
-       179, 383, 383, 383, 383, 172, 383, 0
+       1, 0, 2, 3, 3, 4, 1, 0, 
+       5, 5, 4, 0, 4, 0, 6, 6, 
+       7, 1, 0, 8, 8, 7, 0, 7, 
+       0, 9, 9, 10, 1, 0, 11, 11, 
+       10, 0, 10, 0, 12, 12, 13, 1, 
+       0, 14, 14, 13, 0, 13, 0, 15, 
+       0, 0, 0, 1, 0, 16, 0, 17, 
+       0, 18, 12, 12, 13, 1, 0, 19, 
+       0, 20, 0, 21, 9, 9, 10, 1, 
+       0, 22, 0, 23, 0, 24, 6, 6, 
+       7, 1, 0, 25, 0, 26, 0, 2, 
+       3, 3, 4, 1, 0, 0, 0, 0, 
+       27, 0, 28, 3, 3, 4, 1, 0, 
+       28, 3, 3, 4, 1, 0, 0, 0, 
+       0, 29, 0, 30, 3, 3, 4, 1, 
+       0, 30, 3, 3, 4, 1, 0, 0, 
+       0, 0, 31, 0, 32, 3, 3, 4, 
+       1, 0, 32, 3, 3, 4, 1, 0, 
+       0, 0, 0, 33, 0, 34, 3, 3, 
+       4, 1, 0, 34, 3, 3, 4, 1, 
+       0, 0, 0, 0, 35, 0, 37, 36, 
+       38, 39, 39, 40, 37, 36, 41, 41, 
+       40, 36, 40, 36, 42, 42, 43, 37, 
+       36, 44, 44, 43, 36, 43, 36, 45, 
+       45, 46, 37, 36, 47, 47, 46, 36, 
+       46, 36, 48, 48, 49, 37, 36, 50, 
+       50, 49, 36, 49, 36, 51, 36, 36, 
+       36, 37, 36, 52, 36, 53, 36, 54, 
+       48, 48, 49, 37, 36, 55, 36, 56, 
+       36, 57, 45, 45, 46, 37, 36, 58, 
+       36, 59, 36, 60, 42, 42, 43, 37, 
+       36, 61, 36, 62, 36, 38, 39, 39, 
+       40, 37, 36, 36, 36, 36, 63, 36, 
+       64, 39, 39, 40, 37, 36, 64, 39, 
+       39, 40, 37, 36, 36, 36, 36, 65, 
+       36, 66, 39, 39, 40, 37, 36, 66, 
+       39, 39, 40, 37, 36, 36, 36, 36, 
+       67, 36, 68, 39, 39, 40, 37, 36, 
+       68, 39, 39, 40, 37, 36, 36, 36, 
+       36, 69, 36, 70, 39, 39, 40, 37, 
+       36, 70, 39, 39, 40, 37, 36, 36, 
+       36, 36, 71, 36, 73, 72, 74, 75, 
+       75, 76, 73, 72, 78, 78, 76, 77, 
+       76, 77, 79, 79, 80, 73, 72, 81, 
+       81, 80, 72, 80, 72, 82, 82, 83, 
+       73, 72, 84, 84, 83, 72, 83, 72, 
+       85, 85, 86, 73, 72, 87, 87, 86, 
+       72, 86, 72, 88, 72, 72, 72, 73, 
+       72, 89, 72, 90, 72, 91, 85, 85, 
+       86, 73, 72, 92, 72, 93, 72, 94, 
+       82, 82, 83, 73, 72, 95, 72, 96, 
+       72, 97, 79, 79, 80, 73, 72, 98, 
+       72, 99, 72, 74, 75, 75, 76, 73, 
+       72, 72, 72, 72, 100, 72, 101, 75, 
+       75, 76, 73, 72, 101, 75, 75, 76, 
+       73, 72, 72, 72, 72, 102, 72, 103, 
+       75, 75, 76, 73, 72, 103, 75, 75, 
+       76, 73, 72, 72, 72, 72, 104, 72, 
+       105, 75, 75, 76, 73, 72, 105, 75, 
+       75, 76, 73, 72, 72, 72, 72, 106, 
+       72, 107, 75, 75, 76, 73, 72, 109, 
+       108, 110, 111, 111, 112, 109, 108, 113, 
+       113, 112, 108, 112, 108, 114, 114, 115, 
+       109, 108, 116, 116, 115, 108, 115, 108, 
+       117, 117, 118, 109, 108, 119, 119, 118, 
+       108, 118, 108, 120, 120, 121, 109, 108, 
+       122, 122, 121, 108, 121, 108, 123, 108, 
+       108, 108, 109, 108, 124, 108, 125, 108, 
+       126, 120, 120, 121, 109, 108, 127, 108, 
+       128, 108, 129, 117, 117, 118, 109, 108, 
+       130, 108, 131, 108, 132, 114, 114, 115, 
+       109, 108, 133, 108, 134, 108, 110, 111, 
+       111, 112, 109, 108, 108, 108, 108, 135, 
+       108, 136, 111, 111, 112, 109, 108, 136, 
+       111, 111, 112, 109, 108, 108, 108, 108, 
+       137, 108, 138, 111, 111, 112, 109, 108, 
+       138, 111, 111, 112, 109, 108, 108, 108, 
+       108, 139, 108, 140, 111, 111, 112, 109, 
+       108, 140, 111, 111, 112, 109, 108, 108, 
+       108, 108, 141, 108, 142, 111, 111, 112, 
+       109, 108, 142, 111, 111, 112, 109, 108, 
+       108, 108, 108, 143, 108, 107, 75, 75, 
+       76, 73, 72, 72, 72, 72, 144, 72, 
+       78, 78, 76, 1, 0, 146, 145, 148, 
+       149, 150, 151, 152, 153, 76, 73, 147, 
+       154, 155, 155, 144, 147, 156, 157, 147, 
+       158, 159, 147, 161, 162, 163, 164, 4, 
+       1, 160, 165, 160, 160, 35, 160, 166, 
+       162, 167, 167, 4, 1, 160, 165, 160, 
+       162, 167, 167, 4, 1, 160, 165, 160, 
+       168, 160, 160, 160, 17, 169, 160, 1, 
+       160, 165, 160, 160, 160, 160, 160, 168, 
+       160, 170, 171, 172, 173, 4, 1, 160, 
+       165, 160, 160, 33, 160, 174, 171, 175, 
+       175, 4, 1, 160, 165, 160, 171, 175, 
+       175, 4, 1, 160, 165, 160, 176, 160, 
+       160, 160, 17, 177, 160, 1, 160, 165, 
+       160, 160, 160, 160, 160, 176, 160, 178, 
+       179, 180, 181, 4, 1, 160, 165, 160, 
+       160, 31, 160, 182, 179, 183, 183, 4, 
+       1, 160, 165, 160, 179, 183, 183, 4, 
+       1, 160, 165, 160, 184, 160, 160, 160, 
+       17, 185, 160, 1, 160, 165, 160, 160, 
+       160, 160, 160, 184, 160, 186, 187, 188, 
+       189, 4, 1, 160, 165, 160, 160, 29, 
+       160, 190, 187, 191, 191, 4, 1, 160, 
+       165, 160, 187, 191, 191, 4, 1, 160, 
+       165, 160, 192, 160, 160, 160, 17, 193, 
+       160, 1, 160, 165, 160, 160, 160, 160, 
+       160, 192, 160, 194, 195, 196, 197, 4, 
+       1, 160, 165, 160, 160, 27, 160, 198, 
+       195, 199, 199, 4, 1, 160, 165, 160, 
+       195, 199, 199, 4, 1, 160, 165, 160, 
+       17, 200, 160, 1, 160, 165, 160, 201, 
+       201, 160, 1, 160, 165, 160, 202, 160, 
+       160, 203, 160, 165, 160, 165, 160, 204, 
+       160, 205, 160, 202, 160, 160, 160, 160, 
+       165, 160, 17, 160, 201, 201, 160, 1, 
+       160, 165, 160, 201, 200, 160, 1, 160, 
+       165, 160, 206, 26, 207, 208, 7, 1, 
+       160, 165, 160, 26, 207, 208, 7, 1, 
+       160, 165, 160, 207, 207, 7, 1, 160, 
+       165, 160, 209, 23, 210, 211, 10, 1, 
+       160, 165, 160, 23, 210, 211, 10, 1, 
+       160, 165, 160, 210, 210, 10, 1, 160, 
+       165, 160, 212, 20, 213, 214, 13, 1, 
+       160, 165, 160, 20, 213, 214, 13, 1, 
+       160, 165, 160, 213, 213, 13, 1, 160, 
+       165, 160, 215, 17, 201, 216, 160, 1, 
+       160, 165, 160, 17, 201, 216, 160, 1, 
+       160, 165, 160, 194, 195, 199, 199, 4, 
+       1, 160, 165, 160, 194, 195, 196, 199, 
+       4, 1, 160, 165, 160, 160, 27, 160, 
+       192, 160, 217, 160, 201, 201, 160, 1, 
+       160, 165, 160, 160, 160, 160, 160, 192, 
+       160, 192, 160, 160, 160, 201, 201, 160, 
+       1, 160, 165, 160, 160, 160, 160, 160, 
+       192, 160, 192, 160, 160, 160, 201, 193, 
+       160, 1, 160, 165, 160, 160, 160, 160, 
+       160, 192, 160, 186, 187, 191, 191, 4, 
+       1, 160, 165, 160, 186, 187, 188, 191, 
+       4, 1, 160, 165, 160, 160, 29, 160, 
+       184, 160, 218, 160, 201, 201, 160, 1, 
+       160, 165, 160, 160, 160, 160, 160, 184, 
+       160, 184, 160, 160, 160, 201, 201, 160, 
+       1, 160, 165, 160, 160, 160, 160, 160, 
+       184, 160, 184, 160, 160, 160, 201, 185, 
+       160, 1, 160, 165, 160, 160, 160, 160, 
+       160, 184, 160, 178, 179, 183, 183, 4, 
+       1, 160, 165, 160, 178, 179, 180, 183, 
+       4, 1, 160, 165, 160, 160, 31, 160, 
+       176, 160, 219, 160, 201, 201, 160, 1, 
+       160, 165, 160, 160, 160, 160, 160, 176, 
+       160, 176, 160, 160, 160, 201, 201, 160, 
+       1, 160, 165, 160, 160, 160, 160, 160, 
+       176, 160, 176, 160, 160, 160, 201, 177, 
+       160, 1, 160, 165, 160, 160, 160, 160, 
+       160, 176, 160, 170, 171, 175, 175, 4, 
+       1, 160, 165, 160, 170, 171, 172, 175, 
+       4, 1, 160, 165, 160, 160, 33, 160, 
+       168, 160, 220, 160, 201, 201, 160, 1, 
+       160, 165, 160, 160, 160, 160, 160, 168, 
+       160, 168, 160, 160, 160, 201, 201, 160, 
+       1, 160, 165, 160, 160, 160, 160, 160, 
+       168, 160, 168, 160, 160, 160, 201, 169, 
+       160, 1, 160, 165, 160, 160, 160, 160, 
+       160, 168, 160, 161, 162, 167, 167, 4, 
+       1, 160, 165, 160, 161, 162, 163, 167, 
+       4, 1, 160, 165, 160, 160, 35, 160, 
+       222, 223, 224, 225, 40, 37, 221, 226, 
+       221, 221, 71, 221, 227, 223, 228, 225, 
+       40, 37, 221, 226, 221, 223, 228, 225, 
+       40, 37, 221, 226, 221, 229, 221, 221, 
+       221, 53, 230, 221, 37, 221, 226, 221, 
+       221, 221, 221, 221, 229, 221, 231, 232, 
+       233, 234, 40, 37, 221, 226, 221, 221, 
+       69, 221, 235, 232, 236, 236, 40, 37, 
+       221, 226, 221, 232, 236, 236, 40, 37, 
+       221, 226, 221, 237, 221, 221, 221, 53, 
+       238, 221, 37, 221, 226, 221, 221, 221, 
+       221, 221, 237, 221, 239, 240, 241, 242, 
+       40, 37, 221, 226, 221, 221, 67, 221, 
+       243, 240, 244, 244, 40, 37, 221, 226, 
+       221, 240, 244, 244, 40, 37, 221, 226, 
+       221, 245, 221, 221, 221, 53, 246, 221, 
+       37, 221, 226, 221, 221, 221, 221, 221, 
+       245, 221, 247, 248, 249, 250, 40, 37, 
+       221, 226, 221, 221, 65, 221, 251, 248, 
+       252, 252, 40, 37, 221, 226, 221, 248, 
+       252, 252, 40, 37, 221, 226, 221, 253, 
+       221, 221, 221, 53, 254, 221, 37, 221, 
+       226, 221, 221, 221, 221, 221, 253, 221, 
+       255, 256, 257, 258, 40, 37, 221, 226, 
+       221, 221, 63, 221, 259, 256, 260, 260, 
+       40, 37, 221, 226, 221, 256, 260, 260, 
+       40, 37, 221, 226, 221, 53, 261, 221, 
+       37, 221, 226, 221, 262, 262, 221, 37, 
+       221, 226, 221, 263, 221, 221, 264, 221, 
+       226, 221, 226, 221, 265, 221, 266, 221, 
+       263, 221, 221, 221, 221, 226, 221, 53, 
+       221, 262, 262, 221, 37, 221, 226, 221, 
+       262, 261, 221, 37, 221, 226, 221, 267, 
+       62, 268, 269, 43, 37, 221, 226, 221, 
+       62, 268, 269, 43, 37, 221, 226, 221, 
+       268, 268, 43, 37, 221, 226, 221, 270, 
+       59, 271, 272, 46, 37, 221, 226, 221, 
+       59, 271, 272, 46, 37, 221, 226, 221, 
+       271, 271, 46, 37, 221, 226, 221, 273, 
+       56, 274, 275, 49, 37, 221, 226, 221, 
+       56, 274, 275, 49, 37, 221, 226, 221, 
+       274, 274, 49, 37, 221, 226, 221, 276, 
+       53, 262, 277, 221, 37, 221, 226, 221, 
+       53, 262, 277, 221, 37, 221, 226, 221, 
+       255, 256, 260, 260, 40, 37, 221, 226, 
+       221, 255, 256, 257, 260, 40, 37, 221, 
+       226, 221, 221, 63, 221, 253, 221, 278, 
+       221, 262, 262, 221, 37, 221, 226, 221, 
+       221, 221, 221, 221, 253, 221, 253, 221, 
+       221, 221, 262, 262, 221, 37, 221, 226, 
+       221, 221, 221, 221, 221, 253, 221, 253, 
+       221, 221, 221, 262, 254, 221, 37, 221, 
+       226, 221, 221, 221, 221, 221, 253, 221, 
+       247, 248, 252, 252, 40, 37, 221, 226, 
+       221, 247, 248, 249, 252, 40, 37, 221, 
+       226, 221, 221, 65, 221, 245, 221, 279, 
+       221, 262, 262, 221, 37, 221, 226, 221, 
+       221, 221, 221, 221, 245, 221, 245, 221, 
+       221, 221, 262, 262, 221, 37, 221, 226, 
+       221, 221, 221, 221, 221, 245, 221, 245, 
+       221, 221, 221, 262, 246, 221, 37, 221, 
+       226, 221, 221, 221, 221, 221, 245, 221, 
+       239, 240, 244, 244, 40, 37, 221, 226, 
+       221, 239, 240, 241, 244, 40, 37, 221, 
+       226, 221, 221, 67, 221, 237, 221, 280, 
+       221, 262, 262, 221, 37, 221, 226, 221, 
+       221, 221, 221, 221, 237, 221, 237, 221, 
+       221, 221, 262, 262, 221, 37, 221, 226, 
+       221, 221, 221, 221, 221, 237, 221, 237, 
+       221, 221, 221, 262, 238, 221, 37, 221, 
+       226, 221, 221, 221, 221, 221, 237, 221, 
+       231, 232, 236, 236, 40, 37, 221, 226, 
+       221, 231, 232, 233, 236, 40, 37, 221, 
+       226, 221, 221, 69, 221, 229, 221, 281, 
+       221, 262, 262, 221, 37, 221, 226, 221, 
+       221, 221, 221, 221, 229, 221, 229, 221, 
+       221, 221, 262, 262, 221, 37, 221, 226, 
+       221, 221, 221, 221, 221, 229, 221, 229, 
+       221, 221, 221, 262, 230, 221, 37, 221, 
+       226, 221, 221, 221, 221, 221, 229, 221, 
+       70, 39, 39, 40, 37, 221, 222, 223, 
+       228, 225, 40, 37, 221, 226, 221, 283, 
+       151, 284, 284, 76, 73, 282, 154, 282, 
+       151, 284, 284, 76, 73, 282, 154, 282, 
+       285, 282, 282, 282, 90, 286, 282, 73, 
+       282, 154, 282, 282, 282, 282, 282, 285, 
+       282, 287, 288, 289, 290, 76, 73, 282, 
+       154, 282, 282, 106, 282, 291, 288, 292, 
+       292, 76, 73, 282, 154, 282, 288, 292, 
+       292, 76, 73, 282, 154, 282, 293, 282, 
+       282, 282, 90, 294, 282, 73, 282, 154, 
+       282, 282, 282, 282, 282, 293, 282, 295, 
+       296, 297, 298, 76, 73, 282, 154, 282, 
+       282, 104, 282, 299, 296, 300, 300, 76, 
+       73, 282, 154, 282, 296, 300, 300, 76, 
+       73, 282, 154, 282, 301, 282, 282, 282, 
+       90, 302, 282, 73, 282, 154, 282, 282, 
+       282, 282, 282, 301, 282, 303, 304, 305, 
+       306, 76, 73, 282, 154, 282, 282, 102, 
+       282, 307, 304, 308, 308, 76, 73, 282, 
+       154, 282, 304, 308, 308, 76, 73, 282, 
+       154, 282, 309, 282, 282, 282, 90, 310, 
+       282, 73, 282, 154, 282, 282, 282, 282, 
+       282, 309, 282, 311, 312, 313, 314, 76, 
+       73, 282, 154, 282, 282, 100, 282, 315, 
+       312, 316, 316, 76, 73, 282, 154, 282, 
+       312, 316, 316, 76, 73, 282, 154, 282, 
+       90, 317, 282, 73, 282, 154, 282, 318, 
+       318, 282, 73, 282, 154, 282, 319, 282, 
+       282, 320, 282, 154, 282, 154, 282, 321, 
+       282, 322, 282, 319, 282, 282, 282, 282, 
+       154, 282, 90, 282, 318, 318, 282, 73, 
+       282, 154, 282, 318, 317, 282, 73, 282, 
+       154, 282, 323, 99, 324, 325, 80, 73, 
+       282, 154, 282, 99, 324, 325, 80, 73, 
+       282, 154, 282, 324, 324, 80, 73, 282, 
+       154, 282, 326, 96, 327, 328, 83, 73, 
+       282, 154, 282, 96, 327, 328, 83, 73, 
+       282, 154, 282, 327, 327, 83, 73, 282, 
+       154, 282, 329, 93, 330, 331, 86, 73, 
+       282, 154, 282, 93, 330, 331, 86, 73, 
+       282, 154, 282, 330, 330, 86, 73, 282, 
+       154, 282, 332, 90, 318, 333, 282, 73, 
+       282, 154, 282, 90, 318, 333, 282, 73, 
+       282, 154, 282, 311, 312, 316, 316, 76, 
+       73, 282, 154, 282, 311, 312, 313, 316, 
+       76, 73, 282, 154, 282, 282, 100, 282, 
+       309, 282, 334, 282, 318, 318, 282, 73, 
+       282, 154, 282, 282, 282, 282, 282, 309, 
+       282, 309, 282, 282, 282, 318, 318, 282, 
+       73, 282, 154, 282, 282, 282, 282, 282, 
+       309, 282, 309, 282, 282, 282, 318, 310, 
+       282, 73, 282, 154, 282, 282, 282, 282, 
+       282, 309, 282, 303, 304, 308, 308, 76, 
+       73, 282, 154, 282, 303, 304, 305, 308, 
+       76, 73, 282, 154, 282, 282, 102, 282, 
+       301, 282, 335, 282, 318, 318, 282, 73, 
+       282, 154, 282, 282, 282, 282, 282, 301, 
+       282, 301, 282, 282, 282, 318, 318, 282, 
+       73, 282, 154, 282, 282, 282, 282, 282, 
+       301, 282, 301, 282, 282, 282, 318, 302, 
+       282, 73, 282, 154, 282, 282, 282, 282, 
+       282, 301, 282, 295, 296, 300, 300, 76, 
+       73, 282, 154, 282, 295, 296, 297, 300, 
+       76, 73, 282, 154, 282, 282, 104, 282, 
+       293, 282, 336, 282, 318, 318, 282, 73, 
+       282, 154, 282, 282, 282, 282, 282, 293, 
+       282, 293, 282, 282, 282, 318, 318, 282, 
+       73, 282, 154, 282, 282, 282, 282, 282, 
+       293, 282, 293, 282, 282, 282, 318, 294, 
+       282, 73, 282, 154, 282, 282, 282, 282, 
+       282, 293, 282, 287, 288, 292, 292, 76, 
+       73, 282, 154, 282, 287, 288, 289, 292, 
+       76, 73, 282, 154, 282, 282, 106, 282, 
+       285, 282, 337, 282, 318, 318, 282, 73, 
+       282, 154, 282, 282, 282, 282, 282, 285, 
+       282, 285, 282, 282, 282, 318, 318, 282, 
+       73, 282, 154, 282, 282, 282, 282, 282, 
+       285, 282, 285, 282, 282, 282, 318, 286, 
+       282, 73, 282, 154, 282, 282, 282, 282, 
+       282, 285, 282, 107, 75, 75, 76, 73, 
+       338, 338, 338, 338, 144, 338, 150, 151, 
+       284, 284, 76, 73, 282, 154, 282, 107, 
+       75, 75, 76, 73, 338, 340, 341, 342, 
+       343, 112, 109, 339, 344, 339, 339, 143, 
+       339, 345, 341, 343, 343, 112, 109, 339, 
+       344, 339, 341, 343, 343, 112, 109, 339, 
+       344, 339, 346, 339, 339, 339, 125, 347, 
+       339, 109, 339, 344, 339, 339, 339, 339, 
+       339, 346, 339, 348, 349, 350, 351, 112, 
+       109, 339, 344, 339, 339, 141, 339, 352, 
+       349, 353, 353, 112, 109, 339, 344, 339, 
+       349, 353, 353, 112, 109, 339, 344, 339, 
+       354, 339, 339, 339, 125, 355, 339, 109, 
+       339, 344, 339, 339, 339, 339, 339, 354, 
+       339, 356, 357, 358, 359, 112, 109, 339, 
+       344, 339, 339, 139, 339, 360, 357, 361, 
+       361, 112, 109, 339, 344, 339, 357, 361, 
+       361, 112, 109, 339, 344, 339, 362, 339, 
+       339, 339, 125, 363, 339, 109, 339, 344, 
+       339, 339, 339, 339, 339, 362, 339, 364, 
+       365, 366, 367, 112, 109, 339, 344, 339, 
+       339, 137, 339, 368, 365, 369, 369, 112, 
+       109, 339, 344, 339, 365, 369, 369, 112, 
+       109, 339, 344, 339, 370, 339, 339, 339, 
+       125, 371, 339, 109, 339, 344, 339, 339, 
+       339, 339, 339, 370, 339, 372, 373, 374, 
+       375, 112, 109, 339, 344, 339, 339, 135, 
+       339, 376, 373, 377, 377, 112, 109, 339, 
+       344, 339, 373, 377, 377, 112, 109, 339, 
+       344, 339, 125, 378, 339, 109, 339, 344, 
+       339, 379, 379, 339, 109, 339, 344, 339, 
+       380, 339, 339, 381, 339, 344, 339, 344, 
+       339, 382, 339, 383, 339, 380, 339, 339, 
+       339, 339, 344, 339, 125, 339, 379, 379, 
+       339, 109, 339, 344, 339, 379, 378, 339, 
+       109, 339, 344, 339, 384, 134, 385, 386, 
+       115, 109, 339, 344, 339, 134, 385, 386, 
+       115, 109, 339, 344, 339, 385, 385, 115, 
+       109, 339, 344, 339, 387, 131, 388, 389, 
+       118, 109, 339, 344, 339, 131, 388, 389, 
+       118, 109, 339, 344, 339, 388, 388, 118, 
+       109, 339, 344, 339, 390, 128, 391, 392, 
+       121, 109, 339, 344, 339, 128, 391, 392, 
+       121, 109, 339, 344, 339, 391, 391, 121, 
+       109, 339, 344, 339, 393, 125, 379, 394, 
+       339, 109, 339, 344, 339, 125, 379, 394, 
+       339, 109, 339, 344, 339, 372, 373, 377, 
+       377, 112, 109, 339, 344, 339, 372, 373, 
+       374, 377, 112, 109, 339, 344, 339, 339, 
+       135, 339, 370, 339, 395, 339, 379, 379, 
+       339, 109, 339, 344, 339, 339, 339, 339, 
+       339, 370, 339, 370, 339, 339, 339, 379, 
+       379, 339, 109, 339, 344, 339, 339, 339, 
+       339, 339, 370, 339, 370, 339, 339, 339, 
+       379, 371, 339, 109, 339, 344, 339, 339, 
+       339, 339, 339, 370, 339, 364, 365, 369, 
+       369, 112, 109, 339, 344, 339, 364, 365, 
+       366, 369, 112, 109, 339, 344, 339, 339, 
+       137, 339, 362, 339, 396, 339, 379, 379, 
+       339, 109, 339, 344, 339, 339, 339, 339, 
+       339, 362, 339, 362, 339, 339, 339, 379, 
+       379, 339, 109, 339, 344, 339, 339, 339, 
+       339, 339, 362, 339, 362, 339, 339, 339, 
+       379, 363, 339, 109, 339, 344, 339, 339, 
+       339, 339, 339, 362, 339, 356, 357, 361, 
+       361, 112, 109, 339, 344, 339, 356, 357, 
+       358, 361, 112, 109, 339, 344, 339, 339, 
+       139, 339, 354, 339, 397, 339, 379, 379, 
+       339, 109, 339, 344, 339, 339, 339, 339, 
+       339, 354, 339, 354, 339, 339, 339, 379, 
+       379, 339, 109, 339, 344, 339, 339, 339, 
+       339, 339, 354, 339, 354, 339, 339, 339, 
+       379, 355, 339, 109, 339, 344, 339, 339, 
+       339, 339, 339, 354, 339, 348, 349, 353, 
+       353, 112, 109, 339, 344, 339, 348, 349, 
+       350, 353, 112, 109, 339, 344, 339, 339, 
+       141, 339, 346, 339, 398, 339, 379, 379, 
+       339, 109, 339, 344, 339, 339, 339, 339, 
+       339, 346, 339, 346, 339, 339, 339, 379, 
+       379, 339, 109, 339, 344, 339, 339, 339, 
+       339, 339, 346, 339, 346, 339, 339, 339, 
+       379, 347, 339, 109, 339, 344, 339, 339, 
+       339, 339, 339, 346, 339, 340, 341, 343, 
+       343, 112, 109, 339, 344, 339, 148, 149, 
+       150, 151, 399, 284, 76, 73, 282, 154, 
+       155, 155, 144, 282, 282, 148, 282, 161, 
+       400, 163, 164, 4, 1, 160, 165, 160, 
+       160, 35, 160, 168, 149, 150, 151, 401, 
+       402, 76, 403, 160, 404, 160, 155, 144, 
+       160, 160, 168, 160, 107, 405, 405, 76, 
+       403, 160, 165, 160, 160, 144, 160, 406, 
+       160, 160, 407, 160, 404, 160, 404, 160, 
+       408, 160, 205, 160, 406, 160, 160, 160, 
+       160, 404, 160, 168, 160, 220, 107, 405, 
+       405, 76, 403, 160, 165, 160, 160, 160, 
+       160, 160, 168, 160, 410, 409, 411, 411, 
+       409, 146, 409, 412, 409, 411, 411, 409, 
+       146, 409, 412, 409, 413, 409, 409, 414, 
+       409, 412, 409, 412, 409, 415, 409, 416, 
+       409, 413, 409, 409, 409, 409, 412, 409, 
+       148, 338, 338, 338, 338, 338, 338, 338, 
+       338, 338, 155, 338, 338, 338, 338, 148, 
+       338, 0
 };
 
 static const short _indic_syllable_machine_trans_targs[] = {
-       166, 188, 2, 194, 3, 5, 197, 6, 
-       8, 200, 9, 11, 203, 12, 14, 15, 
-       187, 17, 18, 202, 20, 21, 199, 23, 
-       24, 196, 205, 208, 212, 214, 218, 220, 
-       224, 226, 230, 232, 166, 255, 37, 261, 
-       38, 40, 264, 41, 43, 267, 44, 46, 
-       270, 47, 49, 50, 254, 52, 53, 269, 
-       55, 56, 266, 58, 59, 263, 272, 275, 
-       279, 281, 285, 287, 291, 293, 297, 300, 
-       166, 321, 72, 327, 166, 73, 75, 330, 
-       76, 78, 333, 79, 81, 336, 82, 84, 
-       85, 320, 87, 88, 335, 90, 91, 332, 
-       93, 94, 329, 338, 341, 345, 347, 351, 
-       353, 357, 359, 363, 166, 389, 106, 395, 
-       107, 109, 398, 110, 112, 401, 113, 115, 
-       404, 116, 118, 119, 388, 121, 122, 403, 
-       124, 125, 400, 127, 128, 397, 406, 409, 
-       413, 415, 419, 421, 425, 427, 431, 433, 
-       366, 142, 444, 144, 447, 438, 145, 147, 
-       450, 148, 150, 453, 151, 154, 155, 455, 
-       157, 158, 452, 160, 161, 449, 163, 164, 
-       446, 166, 458, 166, 167, 234, 301, 303, 
-       365, 367, 323, 368, 434, 435, 340, 456, 
-       463, 166, 168, 170, 34, 233, 190, 207, 
-       169, 33, 171, 228, 172, 174, 32, 227, 
-       173, 31, 175, 222, 176, 178, 30, 221, 
-       177, 29, 179, 216, 180, 182, 28, 215, 
-       181, 27, 183, 210, 184, 186, 26, 209, 
-       185, 25, 193, 0, 189, 192, 191, 166, 
-       1, 195, 4, 22, 198, 7, 19, 201, 
-       10, 16, 204, 13, 206, 211, 213, 217, 
-       219, 223, 225, 229, 231, 166, 235, 237, 
-       69, 299, 257, 274, 236, 68, 238, 295, 
-       239, 241, 67, 294, 240, 66, 242, 289, 
-       243, 245, 65, 288, 244, 64, 246, 283, 
-       247, 249, 63, 282, 248, 62, 250, 277, 
-       251, 253, 61, 276, 252, 60, 260, 35, 
-       256, 259, 258, 166, 36, 262, 39, 57, 
-       265, 42, 54, 268, 45, 51, 271, 48, 
-       273, 278, 280, 284, 286, 290, 292, 296, 
-       298, 166, 302, 103, 304, 361, 305, 307, 
-       102, 360, 306, 101, 308, 355, 309, 311, 
-       100, 354, 310, 99, 312, 349, 313, 315, 
-       98, 348, 314, 97, 316, 343, 317, 319, 
-       96, 342, 318, 95, 326, 70, 322, 325, 
-       324, 166, 71, 328, 74, 92, 331, 77, 
-       89, 334, 80, 86, 337, 83, 339, 344, 
-       346, 350, 352, 356, 358, 362, 364, 166, 
-       166, 369, 371, 138, 137, 391, 408, 370, 
-       372, 429, 373, 375, 136, 428, 374, 135, 
-       376, 423, 377, 379, 134, 422, 378, 133, 
-       380, 417, 381, 383, 132, 416, 382, 131, 
-       384, 411, 385, 387, 130, 410, 386, 129, 
-       394, 104, 390, 393, 392, 166, 105, 396, 
-       108, 126, 399, 111, 123, 402, 114, 120, 
-       405, 117, 407, 412, 414, 418, 420, 424, 
-       426, 430, 432, 139, 436, 437, 443, 440, 
-       140, 439, 442, 441, 141, 445, 143, 162, 
-       448, 146, 159, 451, 149, 156, 454, 152, 
-       153, 166, 457, 165, 460, 459, 462, 461, 
-       166
+       138, 160, 166, 2, 167, 3, 5, 170, 
+       6, 8, 173, 9, 11, 176, 12, 14, 
+       15, 159, 17, 18, 175, 20, 21, 172, 
+       23, 24, 169, 178, 182, 183, 187, 188, 
+       192, 193, 197, 198, 138, 221, 227, 36, 
+       228, 37, 39, 231, 40, 42, 234, 43, 
+       45, 237, 46, 48, 49, 220, 51, 52, 
+       236, 54, 55, 233, 57, 58, 230, 239, 
+       243, 244, 248, 249, 253, 254, 258, 260, 
+       138, 281, 287, 70, 288, 138, 71, 73, 
+       291, 74, 76, 294, 77, 79, 297, 80, 
+       82, 83, 280, 85, 86, 296, 88, 89, 
+       293, 91, 92, 290, 299, 303, 304, 308, 
+       309, 313, 314, 318, 138, 343, 349, 103, 
+       350, 104, 106, 353, 107, 109, 356, 110, 
+       112, 359, 113, 115, 116, 342, 118, 119, 
+       358, 121, 122, 355, 124, 125, 352, 361, 
+       365, 366, 370, 371, 375, 376, 380, 381, 
+       320, 138, 394, 138, 139, 200, 261, 263, 
+       319, 321, 283, 322, 382, 383, 392, 399, 
+       138, 140, 142, 33, 199, 162, 141, 32, 
+       143, 195, 144, 146, 31, 194, 145, 30, 
+       147, 190, 148, 150, 29, 189, 149, 28, 
+       151, 185, 152, 154, 27, 184, 153, 26, 
+       155, 180, 156, 158, 25, 179, 157, 1, 
+       165, 0, 161, 164, 163, 138, 168, 4, 
+       22, 171, 7, 19, 174, 10, 16, 177, 
+       13, 181, 186, 191, 196, 138, 201, 203, 
+       67, 259, 223, 202, 66, 204, 256, 205, 
+       207, 65, 255, 206, 64, 208, 251, 209, 
+       211, 63, 250, 210, 62, 212, 246, 213, 
+       215, 61, 245, 214, 60, 216, 241, 217, 
+       219, 59, 240, 218, 35, 226, 34, 222, 
+       225, 224, 138, 229, 38, 56, 232, 41, 
+       53, 235, 44, 50, 238, 47, 242, 247, 
+       252, 257, 138, 262, 100, 264, 316, 265, 
+       267, 99, 315, 266, 98, 268, 311, 269, 
+       271, 97, 310, 270, 96, 272, 306, 273, 
+       275, 95, 305, 274, 94, 276, 301, 277, 
+       279, 93, 300, 278, 69, 286, 68, 282, 
+       285, 284, 138, 289, 72, 90, 292, 75, 
+       87, 295, 78, 84, 298, 81, 302, 307, 
+       312, 317, 138, 138, 323, 325, 134, 133, 
+       345, 324, 326, 378, 327, 329, 132, 377, 
+       328, 131, 330, 373, 331, 333, 130, 372, 
+       332, 129, 334, 368, 335, 337, 128, 367, 
+       336, 127, 338, 363, 339, 341, 126, 362, 
+       340, 102, 348, 101, 344, 347, 346, 138, 
+       351, 105, 123, 354, 108, 120, 357, 111, 
+       117, 360, 114, 364, 369, 374, 379, 135, 
+       384, 385, 391, 386, 388, 136, 387, 390, 
+       389, 138, 393, 137, 396, 395, 398, 397, 
+       138
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
-       1, 0, 0, 2, 0, 0, 2, 0, 
-       0, 2, 0, 0, 2, 0, 0, 0, 
-       2, 0, 0, 2, 0, 0, 2, 0, 
-       0, 2, 2, 2, 2, 2, 2, 2, 
-       2, 2, 2, 2, 3, 0, 0, 2, 
-       0, 0, 2, 0, 0, 2, 0, 0, 
-       2, 0, 0, 0, 2, 0, 0, 2, 
-       0, 0, 2, 0, 0, 2, 2, 2, 
-       2, 2, 2, 2, 2, 2, 2, 2, 
-       4, 0, 0, 2, 5, 0, 0, 2, 
+       1, 0, 2, 0, 2, 0, 0, 2, 
        0, 0, 2, 0, 0, 2, 0, 0, 
        0, 2, 0, 0, 2, 0, 0, 2, 
-       0, 0, 2, 2, 6, 2, 6, 2, 
-       6, 2, 6, 2, 7, 0, 0, 2
-       0, 0, 2, 0, 0, 2, 0, 0, 
-       2, 0, 0, 0, 2, 0, 0, 2
-       0, 0, 2, 0, 0, 2, 2, 2, 
+       0, 0, 2, 2, 2, 2, 2, 2, 
+       2, 2, 2, 2, 3, 0, 2, 0
+       2, 0, 0, 2, 0, 0, 2, 0, 
+       0, 2, 0, 0, 0, 2, 0, 0
+       2, 0, 0, 2, 0, 0, 2, 2, 
        2, 2, 2, 2, 2, 2, 2, 2, 
-       6, 0, 2, 0, 2, 0, 0, 0, 
-       2, 0, 0, 2, 0, 0, 0, 2
+       4, 0, 2, 0, 2, 5, 0, 0, 
+       2, 0, 0, 2, 0, 0, 2, 0
        0, 0, 2, 0, 0, 2, 0, 0, 
-       2, 8, 0, 11, 2, 2, 6, 0, 
-       12, 12, 0, 2, 6, 2, 6, 2, 
-       0, 13, 2, 0, 0, 2, 0, 2, 
-       2, 0, 2, 2, 2, 0, 0, 2, 
-       2, 0, 2, 2, 2, 0, 0, 2, 
-       2, 0, 2, 2, 2, 0, 0, 2, 
-       2, 0, 2, 2, 2, 0, 0, 2, 
-       2, 0, 2, 0, 0, 0, 0, 14, 
-       0, 2, 0, 0, 2, 0, 0, 2, 
-       0, 0, 2, 0, 2, 2, 2, 2, 
-       2, 2, 2, 2, 2, 15, 2, 0, 
-       0, 2, 0, 2, 2, 0, 2, 2, 
-       2, 0, 0, 2, 2, 0, 2, 2, 
-       2, 0, 0, 2, 2, 0, 2, 2, 
-       2, 0, 0, 2, 2, 0, 2, 2, 
-       2, 0, 0, 2, 2, 0, 2, 0, 
-       0, 0, 0, 16, 0, 2, 0, 0, 
+       2, 0, 0, 2, 6, 2, 6, 2, 
+       6, 2, 6, 2, 7, 0, 2, 0, 
        2, 0, 0, 2, 0, 0, 2, 0, 
+       0, 2, 0, 0, 0, 2, 0, 0, 
+       2, 0, 0, 2, 0, 0, 2, 2, 
        2, 2, 2, 2, 2, 2, 2, 2, 
-       2, 17, 6, 0, 6, 6, 6, 0, 
-       0, 6, 6, 0, 6, 6, 6, 0, 
-       0, 6, 6, 0, 6, 6, 6, 0, 
-       0, 6, 6, 0, 6, 6, 6, 0, 
-       0, 6, 6, 0, 6, 0, 0, 0, 
-       0, 18, 0, 2, 0, 0, 2, 0, 
-       0, 2, 0, 0, 2, 0, 2, 2, 
-       2, 2, 2, 2, 2, 2, 2, 19, 
-       20, 2, 0, 0, 0, 0, 2, 2, 
+       6, 8, 0, 11, 2, 2, 6, 0, 
+       12, 12, 0, 2, 6, 2, 2, 0, 
+       13, 2, 0, 0, 2, 0, 2, 0, 
        2, 2, 2, 0, 0, 2, 2, 0, 
        2, 2, 2, 0, 0, 2, 2, 0, 
        2, 2, 2, 0, 0, 2, 2, 0, 
        2, 2, 2, 0, 0, 2, 2, 0, 
-       2, 0, 0, 0, 0, 21, 0, 2, 
-       0, 0, 2, 0, 0, 2, 0, 0, 
-       2, 0, 2, 2, 2, 2, 2, 2, 
-       2, 2, 2, 0, 0, 22, 2, 0, 
-       0, 0, 0, 0, 0, 2, 0, 0, 
+       2, 0, 0, 0, 0, 14, 2, 0, 
+       0, 2, 0, 0, 2, 0, 0, 2, 
+       0, 2, 2, 2, 2, 15, 2, 0, 
+       0, 2, 0, 2, 0, 2, 2, 2, 
+       0, 0, 2, 2, 0, 2, 2, 2, 
+       0, 0, 2, 2, 0, 2, 2, 2, 
+       0, 0, 2, 2, 0, 2, 2, 2, 
+       0, 0, 2, 2, 0, 2, 0, 0, 
+       0, 0, 16, 2, 0, 0, 2, 0, 
+       0, 2, 0, 0, 2, 0, 2, 2, 
+       2, 2, 17, 6, 0, 6, 2, 6, 
+       0, 0, 6, 6, 0, 6, 2, 6, 
+       0, 0, 6, 6, 0, 6, 2, 6, 
+       0, 0, 6, 6, 0, 6, 2, 6, 
+       0, 0, 6, 6, 0, 2, 0, 0, 
+       0, 0, 18, 2, 0, 0, 2, 0, 
+       0, 2, 0, 0, 2, 0, 2, 2, 
+       2, 2, 19, 20, 2, 0, 0, 0, 
+       0, 2, 2, 2, 2, 0, 0, 2, 
+       2, 0, 2, 2, 2, 0, 0, 2, 
+       2, 0, 2, 2, 2, 0, 0, 2, 
+       2, 0, 2, 2, 2, 0, 0, 2, 
+       2, 0, 2, 0, 0, 0, 0, 21, 
        2, 0, 0, 2, 0, 0, 2, 0, 
+       0, 2, 0, 2, 2, 2, 2, 0, 
+       0, 22, 22, 0, 0, 0, 0, 0, 
        0, 23, 2, 0, 0, 0, 0, 0, 
        24
 };
@@ -937,15 +759,7 @@ static const char _indic_syllable_machine_to_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 9, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 9, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
@@ -998,15 +812,7 @@ static const char _indic_syllable_machine_from_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 10, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 10, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1046,67 +852,59 @@ static const short _indic_syllable_machine_eof_trans[] = {
        1, 1, 1, 1, 1, 1, 1, 1, 
        1, 1, 1, 1, 1, 1, 1, 1, 
        1, 1, 1, 1, 1, 1, 1, 1, 
-       1, 1, 1, 37, 37, 37, 37, 37, 
+       1, 1, 37, 37, 37, 37, 37, 37, 
        37, 37, 37, 37, 37, 37, 37, 37, 
        37, 37, 37, 37, 37, 37, 37, 37, 
        37, 37, 37, 37, 37, 37, 37, 37, 
-       37, 37, 37, 37, 37, 37, 73, 73, 
-       77, 77, 73, 73, 73, 73, 73, 73, 
+       37, 37, 37, 37, 73, 73, 78, 78, 
        73, 73, 73, 73, 73, 73, 73, 73, 
        73, 73, 73, 73, 73, 73, 73, 73, 
        73, 73, 73, 73, 73, 73, 73, 73, 
+       73, 73, 73, 73, 73, 109, 109, 109, 
        109, 109, 109, 109, 109, 109, 109, 109, 
        109, 109, 109, 109, 109, 109, 109, 109, 
        109, 109, 109, 109, 109, 109, 109, 109, 
-       109, 109, 109, 109, 109, 109, 109, 109, 
-       109, 109, 109, 73, 1, 1, 1, 1, 
-       1, 1, 1, 1, 1, 1, 1, 1, 
-       1, 1, 1, 1, 1, 1, 1, 1, 
-       1, 1, 1, 1, 1, 170, 0, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 254, 254, 254, 
-       254, 254, 254, 254, 254, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 322, 322, 322, 
-       322, 322, 322, 322, 322, 384, 322, 384, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 385, 385, 385, 385, 385, 385, 
-       385, 385, 322, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       186, 186, 186, 186, 186, 186, 186, 186, 
-       474, 474, 474, 474, 474, 474, 474, 384
+       109, 109, 109, 109, 109, 109, 109, 73, 
+       1, 146, 0, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 222, 222, 222, 
+       222, 222, 222, 222, 222, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 283, 
+       283, 283, 283, 283, 283, 283, 283, 339, 
+       283, 339, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 340, 340, 
+       340, 340, 340, 340, 340, 340, 283, 161, 
+       161, 161, 161, 161, 161, 161, 161, 161, 
+       410, 410, 410, 410, 410, 410, 410, 339
 };
 
-static const int indic_syllable_machine_start = 166;
-static const int indic_syllable_machine_first_final = 166;
+static const int indic_syllable_machine_start = 138;
+static const int indic_syllable_machine_first_final = 138;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 166;
+static const int indic_syllable_machine_en_main = 138;
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.rl"
@@ -1118,10 +916,9 @@ static const int indic_syllable_machine_en_main = 166;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -1129,11 +926,11 @@ static const int indic_syllable_machine_en_main = 166;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 1137 "hb-ot-shape-complex-indic-machine.hh"
+#line 934 "hb-ot-shape-complex-indic-machine.hh"
        {
        cs = indic_syllable_machine_start;
        ts = 0;
@@ -1141,16 +938,15 @@ find_syllables (hb_buffer_t *buffer)
        act = 0;
        }
 
-#line 113 "hb-ot-shape-complex-indic-machine.rl"
+#line 112 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 1154 "hb-ot-shape-complex-indic-machine.hh"
+#line 950 "hb-ot-shape-complex-indic-machine.hh"
        {
        int _slen;
        int _trans;
@@ -1164,7 +960,7 @@ _resume:
 #line 1 "NONE"
        {ts = p;}
        break;
-#line 1168 "hb-ot-shape-complex-indic-machine.hh"
+#line 964 "hb-ot-shape-complex-indic-machine.hh"
        }
 
        _keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1287,7 +1083,7 @@ _eof_trans:
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
        {act = 6;}
        break;
-#line 1291 "hb-ot-shape-complex-indic-machine.hh"
+#line 1087 "hb-ot-shape-complex-indic-machine.hh"
        }
 
 _again:
@@ -1296,7 +1092,7 @@ _again:
 #line 1 "NONE"
        {ts = 0;}
        break;
-#line 1300 "hb-ot-shape-complex-indic-machine.hh"
+#line 1096 "hb-ot-shape-complex-indic-machine.hh"
        }
 
        if ( ++p != pe )
@@ -1312,7 +1108,7 @@ _again:
 
        }
 
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
+#line 120 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
index 35e7ce9..c5d945d 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
   machine indic_syllable_machine;
@@ -52,7 +52,6 @@ DOTTEDCIRCLE = 12;
 RS    = 13;
 Repha = 15;
 Ra    = 16;
-CM    = 17;
 Symbol= 18;
 CS    = 19;
 
@@ -68,15 +67,16 @@ matra_group = z{0,3}.M.N?.(H | forced_rakar)?;
 syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}?;
 halant_group = (z?.H.(ZWJ.N?)?);
 final_halant_group = halant_group | H.ZWNJ;
-medial_group = CM?;
-halant_or_matra_group = (final_halant_group | (H.ZWJ)? matra_group{0,4});
+halant_or_matra_group = (final_halant_group | matra_group{0,4});
 
+complex_syllable_tail = (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
 
-consonant_syllable =   (Repha|CS)? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail;
-vowel_syllable =       reph? V.n? (ZWJ | (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail);
-standalone_cluster =   ((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
+
+consonant_syllable =   (Repha|CS)? cn complex_syllable_tail;
+vowel_syllable =       reph? V.n? (ZWJ | complex_syllable_tail);
+standalone_cluster =   ((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? complex_syllable_tail;
 symbol_cluster =       symbol syllable_tail;
-broken_cluster =       reph? n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
+broken_cluster =       reph? n? complex_syllable_tail;
 other =                        any;
 
 main := |*
@@ -93,10 +93,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -104,7 +103,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -115,7 +114,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
deleted file mode 100644 (file)
index 9554994..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh" /* XXX Remove */
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
-
-
-#define INDIC_TABLE_ELEMENT_TYPE uint16_t
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
-  OT_X = 0,
-  OT_C = 1,
-  OT_V = 2,
-  OT_N = 3,
-  OT_H = 4,
-  OT_ZWNJ = 5,
-  OT_ZWJ = 6,
-  OT_M = 7,
-  OT_SM = 8,
-  /* OT_VD = 9, UNUSED; we use OT_A instead. */
-  OT_A = 10,
-  OT_PLACEHOLDER = 11,
-  OT_DOTTEDCIRCLE = 12,
-  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
-  OT_Coeng = 14, /* Khmer-style Virama. */
-  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
-  OT_Ra = 16,
-  OT_CM = 17,  /* Consonant-Medial. */
-  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
-  OT_CS = 19
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
- * cannot happen in a consonant syllable.  The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
-  POS_START = 0,
-
-  POS_RA_TO_BECOME_REPH = 1,
-  POS_PRE_M = 2,
-  POS_PRE_C = 3,
-
-  POS_BASE_C = 4,
-  POS_AFTER_MAIN = 5,
-
-  POS_ABOVE_C = 6,
-
-  POS_BEFORE_SUB = 7,
-  POS_BELOW_C = 8,
-  POS_AFTER_SUB = 9,
-
-  POS_BEFORE_POST = 10,
-  POS_POST_C = 11,
-  POS_AFTER_POST = 12,
-
-  POS_FINAL_C = 13,
-  POS_SMVD = 14,
-
-  POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
-  INDIC_SYLLABIC_CATEGORY_OTHER                                = OT_X,
-
-  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                     = OT_Symbol,
-  INDIC_SYLLABIC_CATEGORY_BINDU                                = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER                = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK            = OT_A,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT                    = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD               = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL              = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER                = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER             = OT_M, /* U+17CD only. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL             = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER                = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA    = OT_Repha,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED           = OT_X, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED          = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA   = OT_N,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER       = OT_CS,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK              = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER            = OT_Coeng,
-  INDIC_SYLLABIC_CATEGORY_JOINER                       = OT_ZWJ,
-  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER             = OT_X,
-  INDIC_SYLLABIC_CATEGORY_NON_JOINER                   = OT_ZWNJ,
-  INDIC_SYLLABIC_CATEGORY_NUKTA                                = OT_N,
-  INDIC_SYLLABIC_CATEGORY_NUMBER                       = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                        = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                  = OT_M, /* Is like a vowel matra. */
-  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER             = OT_RS,
-  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER            = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                  = OT_X,
-  INDIC_SYLLABIC_CATEGORY_TONE_MARK                    = OT_N,
-  INDIC_SYLLABIC_CATEGORY_VIRAMA                       = OT_H,
-  INDIC_SYLLABIC_CATEGORY_VISARGA                      = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_VOWEL                                = OT_V,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT              = OT_M,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT            = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
-  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                  = POS_END,
-
-  INDIC_MATRA_CATEGORY_LEFT                            = POS_PRE_C,
-  INDIC_MATRA_CATEGORY_TOP                             = POS_ABOVE_C,
-  INDIC_MATRA_CATEGORY_BOTTOM                          = POS_BELOW_C,
-  INDIC_MATRA_CATEGORY_RIGHT                           = POS_POST_C,
-
-  /* These should resolve to the position of the last part of the split sequence. */
-  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                        = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                  = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                  = INDIC_MATRA_CATEGORY_BOTTOM,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT                = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                    = INDIC_MATRA_CATEGORY_TOP,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT          = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
-
-  INDIC_MATRA_CATEGORY_OVERSTRUCK                      = POS_AFTER_MAIN,
-  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT               = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
-  ( \
-    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
-    ( S | \
-     ( \
-      ( \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
-       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
-       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
-       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
-       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
-       false \
-       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
-      ) << 8 \
-     ) \
-    ) \
-   )
-
-HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
-  /* If it ligated, all bets are off. */
-  if (_hb_glyph_info_ligated (&info)) return false;
-  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u)      POS_PRE_M
-#define MATRA_POS_RIGHT(u)     ( \
-                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                 IS_BENG(u) ? POS_AFTER_POST : \
-                                 IS_GURU(u) ? POS_AFTER_POST : \
-                                 IS_GUJR(u) ? POS_AFTER_POST : \
-                                 IS_ORYA(u) ? POS_AFTER_POST : \
-                                 IS_TAML(u) ? POS_AFTER_POST : \
-                                 IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                 IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                 IS_MLYM(u) ? POS_AFTER_POST : \
-                                 IS_SINH(u) ? POS_AFTER_SUB  : \
-                                 /*default*/  POS_AFTER_SUB    \
-                               )
-#define MATRA_POS_TOP(u)       ( /* BENG and MLYM don't have top matras. */ \
-                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                 IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
-                                 IS_GUJR(u) ? POS_AFTER_SUB  : \
-                                 IS_ORYA(u) ? POS_AFTER_MAIN : \
-                                 IS_TAML(u) ? POS_AFTER_SUB  : \
-                                 IS_TELU(u) ? POS_BEFORE_SUB : \
-                                 IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                 IS_SINH(u) ? POS_AFTER_SUB  : \
-                                 /*default*/  POS_AFTER_SUB    \
-                               )
-#define MATRA_POS_BOTTOM(u)    ( \
-                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                 IS_BENG(u) ? POS_AFTER_SUB  : \
-                                 IS_GURU(u) ? POS_AFTER_POST : \
-                                 IS_GUJR(u) ? POS_AFTER_POST : \
-                                 IS_ORYA(u) ? POS_AFTER_SUB  : \
-                                 IS_TAML(u) ? POS_AFTER_POST : \
-                                 IS_TELU(u) ? POS_BEFORE_SUB : \
-                                 IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                 IS_MLYM(u) ? POS_AFTER_POST : \
-                                 IS_SINH(u) ? POS_AFTER_SUB  : \
-                                 /*default*/  POS_AFTER_SUB    \
-                               )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:    return MATRA_POS_LEFT (u);
-    case POS_POST_C:   return MATRA_POS_RIGHT (u);
-    case POS_ABOVE_C:  return MATRA_POS_TOP (u);
-    case POS_BELOW_C:  return MATRA_POS_BOTTOM (u);
-  };
-  return side;
-}
-
-/* XXX
- * This is a hack for now.  We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
-  0x0930u, /* Devanagari */
-  0x09B0u, /* Bengali */
-  0x09F0u, /* Bengali */
-  0x0A30u, /* Gurmukhi */      /* No Reph */
-  0x0AB0u, /* Gujarati */
-  0x0B30u, /* Oriya */
-  0x0BB0u, /* Tamil */         /* No Reph */
-  0x0C30u, /* Telugu */                /* Reph formed only with ZWJ */
-  0x0CB0u, /* Kannada */
-  0x0D30u, /* Malayalam */     /* No Reph, Logical Repha */
-
-  0x0DBBu, /* Sinhala */               /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
-  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
-    if (u == ra_chars[i])
-      return true;
-  return false;
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  /* The following act more like the Bindus. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
-    cat = OT_SM;
-  /* The following act like consonants. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
-                                     0x1CF5u, 0x1CF6u)))
-    cat = OT_C;
-  /* TODO: The following should only be allowed after a Visarga.
-   * For now, just treat them like regular tone marks. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
-    cat = OT_A;
-  /* TODO: The following should only be allowed after some of
-   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
-   * For now, just treat them like tone marks. */
-  else if (unlikely (u == 0x1CEDu))
-    cat = OT_A;
-  /* The following take marks in standalone clusters, similar to Avagraha. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
-                                     0x1CE9u, 0x1CECu,
-                                     0x1CEEu, 0x1CF1u)))
-  {
-    cat = OT_Symbol;
-    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
-  }
-  else if (unlikely (u == 0x0A51u))
-  {
-    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
-    cat = OT_M;
-    pos = POS_BELOW_C;
-  }
-
-  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-   * so the Indic shaper needs to know their categories. */
-  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
-  else if (unlikely (u == 0x1133cu)) cat = OT_N;
-
-  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-
-  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
-  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
-                                   cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (is_ra (u))
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_indic (u, pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
-  info.indic_category() = cat;
-  info.indic_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
index 54291bc..43b5ef8 100644 (file)
  * # Date: 2017-10-16, 24:39:00 GMT [KW]
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 
 #define ISC_A  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                /*  16 chars; Avagraha */
 #define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU                   /*  83 chars; Bindu */
@@ -69,6 +71,7 @@
 #define IMC_TLR        INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT     /*   4 chars; Top_And_Left_And_Right */
 #define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT              /*  13 chars; Top_And_Right */
 #define IMC_VOL        INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT          /*  19 chars; Visual_Order_Left */
+#pragma GCC diagnostic pop
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
 
index 447e36c..d2d0a5a 100644 (file)
@@ -24,8 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
@@ -95,42 +96,41 @@ static const indic_config_t indic_configs[] =
  * Indic shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 indic_features[] =
 {
   /*
    * Basic features.
    * These features are applied in order, one at a time, after initial_reordering.
    */
-  {HB_TAG('n','u','k','t'), F_GLOBAL},
-  {HB_TAG('a','k','h','n'), F_GLOBAL},
-  {HB_TAG('r','p','h','f'), F_NONE},
-  {HB_TAG('r','k','r','f'), F_GLOBAL},
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('h','a','l','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('v','a','t','u'), F_GLOBAL},
-  {HB_TAG('c','j','c','t'), F_GLOBAL},
+  {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','p','h','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after final_reordering
+   * but before clearing syllables.
    * Default Bengali font in Windows for example has intermixed
    * lookups for init,pres,abvs,blws features.
    */
-  {HB_TAG('i','n','i','t'), F_NONE},
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  {HB_TAG('h','a','l','n'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
+  {HB_TAG('i','n','i','t'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -158,12 +158,13 @@ enum {
   _BLWS,
   _PSTS,
   _HALN,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   INDIC_NUM_FEATURES,
-  INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */
+  INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
 };
 
 static void
@@ -191,25 +192,27 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
 
   unsigned int i = 0;
   map->add_gsub_pause (initial_reordering);
+
   for (; i < INDIC_BASIC_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
+    map->add_feature (indic_features[i]);
     map->add_gsub_pause (nullptr);
   }
+
   map->add_gsub_pause (final_reordering);
-  for (; i < INDIC_NUM_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
 
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < INDIC_NUM_FEATURES; i++)
+    map->add_feature (indic_features[i]);
+
+  map->enable_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('c','l','i','g'));
 
   map->add_gsub_pause (clear_syllables);
 }
@@ -217,13 +220,13 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
 static void
 override_features_indic (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -231,9 +234,9 @@ struct would_substitute_feature_t
                            &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                               unsigned int          glyphs_count,
-                               hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                        unsigned int          glyphs_count,
+                        hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -249,12 +252,10 @@ struct would_substitute_feature_t
 
 struct indic_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
-    hb_codepoint_t glyph = virama_glyph;
-    if (unlikely (virama_glyph == (hb_codepoint_t) -1))
+    hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+    if (unlikely (glyph == (hb_codepoint_t) -1))
     {
       if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
        glyph = 0;
@@ -262,8 +263,8 @@ struct indic_shape_plan_t
        * Maybe one day... */
 
       /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
-       * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
-      virama_glyph = glyph;
+       * during shape planning...  Instead, overwrite it here. */
+      virama_glyph.set_relaxed ((int) glyph);
     }
 
     *pglyph = glyph;
@@ -273,7 +274,8 @@ struct indic_shape_plan_t
   const indic_config_t *config;
 
   bool is_old_spec;
-  mutable hb_codepoint_t virama_glyph;
+  bool uniscribe_bug_compatible;
+  mutable hb_atomic_int_t virama_glyph;
 
   would_substitute_feature_t rphf;
   would_substitute_feature_t pref;
@@ -298,7 +300,8 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
     }
 
   indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-  indic_plan->virama_glyph = (hb_codepoint_t) -1;
+  indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+  indic_plan->virama_glyph.set_relaxed (-1);
 
   /* Use zero-context would_substitute() matching for new-spec of the main
    * Indic scripts, and scripts with one spec only, but not for old-specs.
@@ -419,7 +422,7 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
     return;
 
   hb_codepoint_t virama;
-  if (indic_plan->get_virama_glyph (font, &virama))
+  if (indic_plan->load_virama_glyph (font, &virama))
   {
     hb_face_t *face = font->face;
     unsigned int count = buffer->len;
@@ -667,9 +670,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
    * last consonant.
    *
    * Reports suggest that in some scripts Uniscribe does this only if there
-   * is *not* a Halant after last consonant already (eg. Kannada), while it
-   * does it unconditionally in other scripts (eg. Malayalam).  We don't
-   * currently know about other scripts, so we single out Malayalam for now.
+   * is *not* a Halant after last consonant already.  We know that is the
+   * case for Kannada, while it reorders unconditionally in other scripts,
+   * eg. Malayalam, Bengali, and Devanagari.  We don't currently know about
+   * other scripts, so we blacklist Kannada.
    *
    * Kannada test case:
    * U+0C9A,U+0CCD,U+0C9A,U+0CCD
@@ -679,10 +683,20 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
    * Malayalam test case:
    * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
    * With lohit-ttf-20121122/Lohit-Malayalam.ttf
+   *
+   * Bengali test case:
+   * U+0998,U+09CD,U+09AF,U+09CD
+   * With Windows XP vrinda.ttf
+   * https://github.com/harfbuzz/harfbuzz/issues/1073
+   *
+   * Devanagari test case:
+   * U+091F,U+094D,U+0930,U+094D
+   * With chandas.ttf
+   * https://github.com/harfbuzz/harfbuzz/issues/1071
    */
   if (indic_plan->is_old_spec)
   {
-    bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM;
+    bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
     for (unsigned int i = base + 1; i < end; i++)
       if (info[i].indic_category() == OT_H)
       {
@@ -706,7 +720,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
     indic_position_t last_pos = POS_START;
     for (unsigned int i = start; i < end; i++)
     {
-      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
+      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | FLAG (OT_H))))
       {
        info[i].indic_position() = last_pos;
        if (unlikely (info[i].indic_category() == OT_H &&
@@ -772,8 +786,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
      *
      * We could use buffer->sort() for this, if there was no special
      * reordering of pre-base stuff happening later...
+     * We don't want to merge_clusters all of that, which buffer->sort()
+     * would.
      */
-    if (indic_plan->is_old_spec || end - base > 127)
+    if (indic_plan->is_old_spec || end - start > 127)
       buffer->merge_clusters (base, end);
     else
     {
@@ -902,10 +918,12 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
                                       hb_buffer_t *buffer,
                                       unsigned int start, unsigned int end)
 {
+  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+
   /* We treat placeholder/dotted-circle as if they are consonants, so we
    * should just chain.  Only if not in compatibility mode that is... */
 
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     /* For dotted-circle, this is what Uniscribe does:
      * If dotted-circle is the last glyph, it just does nothing.
@@ -947,7 +965,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
                       hb_font_t *font,
                       hb_buffer_t *buffer)
 {
-  /* Note: This loop is extra overhead, but should not be measurable. */
+  /* Note: This loop is extra overhead, but should not be measurable.
+   * TODO Use a buffer scratch flag to remove the loop. */
   bool has_broken_syllables = false;
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -999,7 +1018,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -1029,9 +1047,11 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
    * phase, and that might have messed up our properties.  Recover
    * from a particular case of that where we're fairly sure that a
    * class of OT_H is desired but has been lost. */
-  if (indic_plan->virama_glyph)
+  /* We don't call load_virama_glyph(), since we know it's already
+   * loaded. */
+  hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+  if (virama_glyph)
   {
-    unsigned int virama_glyph = indic_plan->virama_glyph;
     for (unsigned int i = start; i < end; i++)
       if (info[i].codepoint == virama_glyph &&
          _hb_glyph_info_ligated (&info[i]) &&
@@ -1120,6 +1140,24 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
    *     defined as “after last standalone halant glyph, after initial matra
    *     position and before the main consonant”. If ZWJ or ZWNJ follow this
    *     halant, position is moved after it.
+   *
+   * IMPLEMENTATION NOTES:
+   *
+   * It looks like the last sentence is wrong.  Testing, with Windows 7 Uniscribe
+   * and Devanagari shows that the behavior is best described as:
+   *
+   * "If ZWJ follows this halant, matra is NOT repositioned after this halant.
+   *  If ZWNJ follows this halant, position is moved after it."
+   *
+   * Test case, with Adobe Devanagari or Nirmala UI:
+   *
+   *   U+091F,U+094D,U+200C,U+092F,U+093F
+   *   (Matra moves to the middle, after ZWNJ.)
+   *
+   *   U+091F,U+094D,U+200D,U+092F,U+093F
+   *   (Matra does NOT move, stays to the left.)
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1070
    */
 
   if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
@@ -1133,6 +1171,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
      */
     if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
     {
+    search:
       while (new_pos > start &&
             !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
        new_pos--;
@@ -1143,9 +1182,27 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
       if (is_halant (info[new_pos]) &&
          info[new_pos].indic_position() != POS_PRE_M)
       {
+#if 0 // See comment above
        /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
        if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
          new_pos++;
+#endif
+       if (new_pos + 1 < end)
+       {
+         /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
+         if (info[new_pos + 1].indic_category() == OT_ZWJ)
+         {
+           /* Keep searching. */
+           if (new_pos > start)
+           {
+             new_pos--;
+             goto search;
+           }
+         }
+         /* -> If ZWNJ follows this halant, position is moved after it. */
+         if (info[new_pos + 1].indic_category() == OT_ZWNJ)
+           new_pos++;
+       }
       }
       else
         new_pos = start; /* No move. */
@@ -1306,7 +1363,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
        * Uniscribe doesn't do this.
        * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
        */
-      if (!hb_options ().uniscribe_bug_compatible &&
+      if (!indic_plan->uniscribe_bug_compatible &&
          unlikely (is_halant (info[new_reph_pos]))) {
        for (unsigned int i = base + 1; i < new_reph_pos; i++)
          if (info[i].indic_category() == OT_M) {
@@ -1412,7 +1469,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
   /*
    * Finish off the clusters and go home!
    */
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     switch ((hb_tag_t) plan->props.script)
     {
@@ -1460,6 +1517,14 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
 }
 
 
+static void
+preprocess_text_indic (const hb_ot_shape_plan_t *plan,
+                      hb_buffer_t              *buffer,
+                      hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+}
+
 static bool
 decompose_indic (const hb_ot_shape_normalize_context_t *c,
                 hb_codepoint_t  ab,
@@ -1559,13 +1624,13 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
   override_features_indic,
   data_create_indic,
   data_destroy_indic,
-  nullptr, /* preprocess_text */
+  preprocess_text_indic,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   decompose_indic,
   compose_indic,
   setup_masks_indic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh
new file mode 100644 (file)
index 0000000..dcc2a7a
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+/* buffer var allocations */
+#define indic_category() complex_var_u8_0() /* indic_category_t */
+#define indic_position() complex_var_u8_1() /* indic_position_t */
+
+
+#define INDIC_TABLE_ELEMENT_TYPE uint16_t
+
+/* Cateories used in the OpenType spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/devanagari
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum indic_category_t {
+  OT_X = 0,
+  OT_C = 1,
+  OT_V = 2,
+  OT_N = 3,
+  OT_H = 4,
+  OT_ZWNJ = 5,
+  OT_ZWJ = 6,
+  OT_M = 7,
+  OT_SM = 8,
+  /* OT_VD = 9, UNUSED; we use OT_A instead. */
+  OT_A = 10,
+  OT_PLACEHOLDER = 11,
+  OT_DOTTEDCIRCLE = 12,
+  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
+  OT_Coeng = 14, /* Khmer-style Virama. */
+  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
+  OT_Ra = 16,
+  OT_CM = 17,  /* Consonant-Medial; Unused by Indic shaper. */
+  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
+  OT_CS = 19
+};
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
+ * cannot happen in a consonant syllable.  The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right! */
+#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
+#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
+
+
+/* Visual positions in a syllable from left to right. */
+enum indic_position_t {
+  POS_START = 0,
+
+  POS_RA_TO_BECOME_REPH = 1,
+  POS_PRE_M = 2,
+  POS_PRE_C = 3,
+
+  POS_BASE_C = 4,
+  POS_AFTER_MAIN = 5,
+
+  POS_ABOVE_C = 6,
+
+  POS_BEFORE_SUB = 7,
+  POS_BELOW_C = 8,
+  POS_AFTER_SUB = 9,
+
+  POS_BEFORE_POST = 10,
+  POS_POST_C = 11,
+  POS_AFTER_POST = 12,
+
+  POS_FINAL_C = 13,
+  POS_SMVD = 14,
+
+  POS_END = 15
+};
+
+/* Categories used in IndicSyllabicCategory.txt from UCD. */
+enum indic_syllabic_category_t {
+  INDIC_SYLLABIC_CATEGORY_OTHER                                = OT_X,
+
+  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                     = OT_Symbol,
+  INDIC_SYLLABIC_CATEGORY_BINDU                                = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER                = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK            = OT_A,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT                    = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD               = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL              = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER                = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER             = OT_M, /* U+17CD only. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL             = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER                = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA    = OT_Repha,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED           = OT_X, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED          = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA   = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER       = OT_CS,
+  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK              = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER            = OT_Coeng,
+  INDIC_SYLLABIC_CATEGORY_JOINER                       = OT_ZWJ,
+  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER             = OT_X,
+  INDIC_SYLLABIC_CATEGORY_NON_JOINER                   = OT_ZWNJ,
+  INDIC_SYLLABIC_CATEGORY_NUKTA                                = OT_N,
+  INDIC_SYLLABIC_CATEGORY_NUMBER                       = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                        = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                  = OT_M, /* Is like a vowel matra. */
+  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER             = OT_RS,
+  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER            = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                  = OT_X,
+  INDIC_SYLLABIC_CATEGORY_TONE_MARK                    = OT_N,
+  INDIC_SYLLABIC_CATEGORY_VIRAMA                       = OT_H,
+  INDIC_SYLLABIC_CATEGORY_VISARGA                      = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_VOWEL                                = OT_V,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT              = OT_M,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT            = OT_V
+};
+
+/* Categories used in IndicSMatraCategory.txt from UCD */
+enum indic_matra_category_t {
+  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                  = POS_END,
+
+  INDIC_MATRA_CATEGORY_LEFT                            = POS_PRE_C,
+  INDIC_MATRA_CATEGORY_TOP                             = POS_ABOVE_C,
+  INDIC_MATRA_CATEGORY_BOTTOM                          = POS_BELOW_C,
+  INDIC_MATRA_CATEGORY_RIGHT                           = POS_POST_C,
+
+  /* These should resolve to the position of the last part of the split sequence. */
+  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                        = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                  = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                  = INDIC_MATRA_CATEGORY_BOTTOM,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT                = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                    = INDIC_MATRA_CATEGORY_TOP,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT          = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
+
+  INDIC_MATRA_CATEGORY_OVERSTRUCK                      = POS_AFTER_MAIN,
+  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT               = POS_PRE_M
+};
+
+#define INDIC_COMBINE_CATEGORIES(S,M) \
+  ( \
+    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
+    ( S | \
+     ( \
+      ( \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
+       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
+       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
+       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
+       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
+       false \
+       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
+      ) << 8 \
+     ) \
+    ) \
+   )
+
+HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
+hb_indic_get_categories (hb_codepoint_t u);
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+  /* If it ligated, all bets are off. */
+  if (_hb_glyph_info_ligated (&info)) return false;
+  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, CONSONANT_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, FLAG (OT_H));
+}
+
+#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
+
+#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
+#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
+#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
+#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
+#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
+#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
+#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
+#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
+#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
+#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
+
+
+#define MATRA_POS_LEFT(u)      POS_PRE_M
+#define MATRA_POS_RIGHT(u)     ( \
+                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                 IS_BENG(u) ? POS_AFTER_POST : \
+                                 IS_GURU(u) ? POS_AFTER_POST : \
+                                 IS_GUJR(u) ? POS_AFTER_POST : \
+                                 IS_ORYA(u) ? POS_AFTER_POST : \
+                                 IS_TAML(u) ? POS_AFTER_POST : \
+                                 IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                 IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                 IS_MLYM(u) ? POS_AFTER_POST : \
+                                 IS_SINH(u) ? POS_AFTER_SUB  : \
+                                 /*default*/  POS_AFTER_SUB    \
+                               )
+#define MATRA_POS_TOP(u)       ( /* BENG and MLYM don't have top matras. */ \
+                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                 IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
+                                 IS_GUJR(u) ? POS_AFTER_SUB  : \
+                                 IS_ORYA(u) ? POS_AFTER_MAIN : \
+                                 IS_TAML(u) ? POS_AFTER_SUB  : \
+                                 IS_TELU(u) ? POS_BEFORE_SUB : \
+                                 IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                 IS_SINH(u) ? POS_AFTER_SUB  : \
+                                 /*default*/  POS_AFTER_SUB    \
+                               )
+#define MATRA_POS_BOTTOM(u)    ( \
+                                 IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                 IS_BENG(u) ? POS_AFTER_SUB  : \
+                                 IS_GURU(u) ? POS_AFTER_POST : \
+                                 IS_GUJR(u) ? POS_AFTER_POST : \
+                                 IS_ORYA(u) ? POS_AFTER_SUB  : \
+                                 IS_TAML(u) ? POS_AFTER_POST : \
+                                 IS_TELU(u) ? POS_BEFORE_SUB : \
+                                 IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                 IS_MLYM(u) ? POS_AFTER_POST : \
+                                 IS_SINH(u) ? POS_AFTER_SUB  : \
+                                 /*default*/  POS_AFTER_SUB    \
+                               )
+
+static inline indic_position_t
+matra_position_indic (hb_codepoint_t u, indic_position_t side)
+{
+  switch ((int) side)
+  {
+    case POS_PRE_C:    return MATRA_POS_LEFT (u);
+    case POS_POST_C:   return MATRA_POS_RIGHT (u);
+    case POS_ABOVE_C:  return MATRA_POS_TOP (u);
+    case POS_BELOW_C:  return MATRA_POS_BOTTOM (u);
+  };
+  return side;
+}
+
+/* XXX
+ * This is a hack for now.  We should move this data into the main Indic table.
+ * Or completely remove it and just check in the tables.
+ */
+static const hb_codepoint_t ra_chars[] = {
+  0x0930u, /* Devanagari */
+  0x09B0u, /* Bengali */
+  0x09F0u, /* Bengali */
+  0x0A30u, /* Gurmukhi */      /* No Reph */
+  0x0AB0u, /* Gujarati */
+  0x0B30u, /* Oriya */
+  0x0BB0u, /* Tamil */         /* No Reph */
+  0x0C30u, /* Telugu */                /* Reph formed only with ZWJ */
+  0x0CB0u, /* Kannada */
+  0x0D30u, /* Malayalam */     /* No Reph, Logical Repha */
+
+  0x0DBBu, /* Sinhala */       /* Reph formed only with ZWJ */
+
+  0x179Au, /* Khmer */
+};
+
+static inline bool
+is_ra (hb_codepoint_t u)
+{
+  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
+    if (u == ra_chars[i])
+      return true;
+  return false;
+}
+
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   */
+
+  /* The following act more like the Bindus. */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
+    cat = OT_SM;
+  /* The following act like consonants. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
+                                     0x1CF5u, 0x1CF6u)))
+    cat = OT_C;
+  /* TODO: The following should only be allowed after a Visarga.
+   * For now, just treat them like regular tone marks. */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
+    cat = OT_A;
+  /* TODO: The following should only be allowed after some of
+   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
+   * For now, just treat them like tone marks. */
+  else if (unlikely (u == 0x1CEDu))
+    cat = OT_A;
+  /* The following take marks in standalone clusters, similar to Avagraha. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
+                                     0x1CE9u, 0x1CECu,
+                                     0x1CEEu, 0x1CF1u)))
+  {
+    cat = OT_Symbol;
+    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
+  }
+  else if (unlikely (u == 0x0A51u))
+  {
+    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
+    cat = OT_M;
+    pos = POS_BELOW_C;
+  }
+
+  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
+   * so the Indic shaper needs to know their categories. */
+  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
+  else if (unlikely (u == 0x1133cu)) cat = OT_N;
+
+  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+
+  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
+  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
+                                   cat = OT_PLACEHOLDER;
+  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+
+
+  /*
+   * Re-assign position.
+   */
+
+  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
+  {
+    pos = POS_BASE_C;
+    if (is_ra (u))
+      cat = OT_Ra;
+  }
+  else if (cat == OT_M)
+  {
+    pos = matra_position_indic (u, pos);
+  }
+  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
+  {
+    pos = POS_SMVD;
+  }
+
+  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
+
+
+
+  info.indic_category() = cat;
+  info.indic_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
index d001021..2bc8ca6 100644 (file)
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
-       7u, 7u, 1u, 16u, 13u, 13u, 1u, 16u, 7u, 13u, 7u, 7u, 1u, 16u, 13u, 13u, 
-       1u, 16u, 7u, 13u, 1u, 16u, 3u, 14u, 3u, 14u, 5u, 14u, 3u, 14u, 5u, 14u, 
-       8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 3u, 14u, 5u, 14u, 
-       3u, 14u, 5u, 14u, 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 
-       3u, 14u, 7u, 13u, 7u, 7u, 1u, 16u, 0
+       5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 
+       5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 
+       5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 16u, 1u, 29u, 5u, 29u, 
+       5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 5u, 26u, 
+       5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 
+       5u, 29u, 0
 };
 
 static const char _khmer_syllable_machine_key_spans[] = {
-       1, 16, 1, 16, 7, 1, 16, 1, 
-       16, 7, 16, 12, 12, 10, 12, 10, 
-       1, 11, 6, 1, 6, 12, 12, 10, 
-       12, 10, 1, 11, 6, 1, 6, 12, 
-       12, 7, 1, 16
+       22, 17, 22, 17, 16, 17, 22, 17, 
+       22, 17, 16, 17, 22, 17, 16, 17, 
+       22, 17, 22, 17, 22, 16, 29, 25, 
+       25, 25, 1, 18, 25, 25, 25, 22, 
+       25, 25, 1, 18, 25, 25, 16, 25, 
+       25
 };
 
 static const short _khmer_syllable_machine_index_offsets[] = {
-       0, 2, 19, 21, 38, 46, 48, 65, 
-       67, 84, 92, 109, 122, 135, 146, 159, 
-       170, 172, 184, 191, 193, 200, 213, 226, 
-       237, 250, 261, 263, 275, 282, 284, 291, 
-       304, 317, 325, 327
+       0, 23, 41, 64, 82, 99, 117, 140, 
+       158, 181, 199, 216, 234, 257, 275, 292, 
+       310, 333, 351, 374, 392, 415, 432, 462, 
+       488, 514, 540, 542, 561, 587, 613, 639, 
+       662, 688, 714, 716, 735, 761, 787, 804, 
+       830
 };
 
 static const char _khmer_syllable_machine_indicies[] = {
-       1, 0, 2, 2, 0, 0, 0, 0, 
+       1, 1, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 2, 
+       3, 0, 0, 0, 0, 4, 0, 1, 
+       1, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 3, 
+       0, 1, 1, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 2, 0, 3, 0, 4, 4, 0, 
+       0, 3, 0, 0, 0, 0, 4, 0, 
+       5, 5, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 4, 0, 1, 0, 
-       0, 0, 0, 0, 5, 0, 7, 6, 
-       8, 8, 6, 6, 6, 6, 6, 6, 
-       6, 6, 6, 6, 6, 6, 6, 8, 
-       6, 9, 6, 10, 10, 6, 6, 6, 
-       6, 6, 6, 6, 6, 6, 6, 6, 
-       6, 6, 10, 6, 7, 6, 6, 6, 
-       6, 6, 11, 6, 4, 4, 13, 12, 
-       14, 15, 7, 16, 12, 12, 4, 4, 
-       11, 17, 12, 4, 12, 19, 18, 20, 
-       21, 1, 22, 18, 18, 18, 18, 5, 
-       23, 18, 24, 18, 21, 21, 1, 22, 
-       18, 18, 18, 18, 18, 23, 18, 21, 
-       21, 1, 22, 18, 18, 18, 18, 18, 
-       23, 18, 25, 18, 21, 21, 1, 22, 
-       18, 18, 18, 18, 18, 26, 18, 21, 
-       21, 1, 22, 18, 18, 18, 18, 18, 
-       26, 18, 27, 18, 28, 18, 29, 18, 
-       18, 22, 18, 18, 18, 18, 3, 18, 
-       30, 18, 18, 18, 18, 22, 18, 22, 
-       18, 28, 18, 18, 18, 18, 22, 18, 
-       19, 18, 21, 21, 1, 22, 18, 18, 
-       18, 18, 18, 23, 18, 32, 31, 33, 
-       33, 7, 16, 31, 31, 31, 31, 31, 
-       34, 31, 33, 33, 7, 16, 31, 31, 
-       31, 31, 31, 34, 31, 35, 31, 33, 
-       33, 7, 16, 31, 31, 31, 31, 31, 
-       36, 31, 33, 33, 7, 16, 31, 31, 
-       31, 31, 31, 36, 31, 37, 31, 38, 
-       31, 39, 31, 31, 16, 31, 31, 31, 
-       31, 9, 31, 40, 31, 31, 31, 31, 
-       16, 31, 16, 31, 38, 31, 31, 31, 
-       31, 16, 31, 13, 31, 41, 33, 7, 
-       16, 31, 31, 31, 31, 11, 34, 31, 
-       13, 31, 33, 33, 7, 16, 31, 31, 
-       31, 31, 31, 34, 31, 7, 42, 42, 
-       42, 42, 42, 11, 42, 7, 42, 10, 
-       10, 42, 42, 42, 42, 42, 42, 42, 
-       42, 42, 42, 42, 42, 42, 10, 42, 
+       4, 0, 6, 6, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 6, 0, 7, 7, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 8, 0, 9, 9, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 10, 0, 0, 
+       0, 0, 4, 0, 9, 9, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 10, 0, 11, 11, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 12, 0, 
+       0, 0, 0, 4, 0, 11, 11, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 12, 0, 13, 
+       13, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 13, 0, 
+       15, 15, 14, 14, 14, 14, 14, 14, 
+       14, 14, 14, 14, 14, 14, 14, 14, 
+       16, 14, 15, 15, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 16, 17, 17, 17, 17, 18, 
+       17, 19, 19, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 18, 17, 20, 20, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 20, 17, 21, 21, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 22, 17, 23, 23, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 24, 17, 
+       17, 17, 17, 18, 17, 23, 23, 17, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 24, 17, 25, 
+       25, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 26, 
+       17, 17, 17, 17, 18, 17, 25, 25, 
+       17, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 26, 17, 
+       15, 15, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 17, 27, 
+       16, 17, 17, 17, 17, 18, 17, 28, 
+       28, 17, 17, 17, 17, 17, 17, 17, 
+       17, 17, 17, 17, 17, 17, 28, 17, 
+       13, 13, 29, 29, 30, 30, 29, 29, 
+       29, 29, 2, 2, 29, 31, 29, 13, 
+       29, 29, 29, 29, 16, 20, 29, 29, 
+       29, 18, 24, 26, 22, 29, 33, 33, 
+       32, 32, 32, 32, 32, 32, 32, 34, 
+       32, 32, 32, 32, 32, 2, 3, 6, 
+       32, 32, 32, 4, 10, 12, 8, 32, 
+       35, 35, 32, 32, 32, 32, 32, 32, 
+       32, 36, 32, 32, 32, 32, 32, 32, 
+       3, 6, 32, 32, 32, 4, 10, 12, 
+       8, 32, 5, 5, 32, 32, 32, 32, 
+       32, 32, 32, 36, 32, 32, 32, 32, 
+       32, 32, 4, 6, 32, 32, 32, 32, 
+       32, 32, 8, 32, 6, 32, 7, 7, 
+       32, 32, 32, 32, 32, 32, 32, 36, 
+       32, 32, 32, 32, 32, 32, 8, 6, 
+       32, 37, 37, 32, 32, 32, 32, 32, 
+       32, 32, 36, 32, 32, 32, 32, 32, 
+       32, 10, 6, 32, 32, 32, 4, 32, 
+       32, 8, 32, 38, 38, 32, 32, 32, 
+       32, 32, 32, 32, 36, 32, 32, 32, 
+       32, 32, 32, 12, 6, 32, 32, 32, 
+       4, 10, 32, 8, 32, 35, 35, 32, 
+       32, 32, 32, 32, 32, 32, 34, 32, 
+       32, 32, 32, 32, 32, 3, 6, 32, 
+       32, 32, 4, 10, 12, 8, 32, 15, 
+       15, 39, 39, 39, 39, 39, 39, 39, 
+       39, 39, 39, 39, 39, 39, 39, 16, 
+       39, 39, 39, 39, 18, 39, 41, 41, 
+       40, 40, 40, 40, 40, 40, 40, 42, 
+       40, 40, 40, 40, 40, 40, 16, 20, 
+       40, 40, 40, 18, 24, 26, 22, 40, 
+       19, 19, 40, 40, 40, 40, 40, 40, 
+       40, 42, 40, 40, 40, 40, 40, 40, 
+       18, 20, 40, 40, 40, 40, 40, 40, 
+       22, 40, 20, 40, 21, 21, 40, 40, 
+       40, 40, 40, 40, 40, 42, 40, 40, 
+       40, 40, 40, 40, 22, 20, 40, 43, 
+       43, 40, 40, 40, 40, 40, 40, 40, 
+       42, 40, 40, 40, 40, 40, 40, 24, 
+       20, 40, 40, 40, 18, 40, 40, 22, 
+       40, 44, 44, 40, 40, 40, 40, 40, 
+       40, 40, 42, 40, 40, 40, 40, 40, 
+       40, 26, 20, 40, 40, 40, 18, 24, 
+       40, 22, 40, 28, 28, 39, 39, 39, 
+       39, 39, 39, 39, 39, 39, 39, 39, 
+       39, 39, 28, 39, 45, 45, 40, 40, 
+       40, 40, 40, 40, 40, 46, 40, 40, 
+       40, 40, 40, 27, 16, 20, 40, 40, 
+       40, 18, 24, 26, 22, 40, 41, 41, 
+       40, 40, 40, 40, 40, 40, 40, 46, 
+       40, 40, 40, 40, 40, 40, 16, 20, 
+       40, 40, 40, 18, 24, 26, 22, 40, 
        0
 };
 
 static const char _khmer_syllable_machine_trans_targs[] = {
-       10, 14, 17, 20, 11, 21, 10, 24
-       27, 30, 31, 32, 10, 22, 33, 34
-       26, 35, 10, 12, 4, 0, 16, 3
-       13, 15, 1, 10, 18, 2, 19, 10
-       23, 5, 8, 25, 6, 10, 28, 7
-       29, 9, 10
+       22, 1, 30, 24, 25, 3, 26, 5
+       27, 7, 28, 9, 29, 23, 22, 11
+       32, 22, 33, 13, 34, 15, 35, 17
+       36, 19, 37, 40, 39, 22, 31, 38
+       22, 0, 10, 2, 4, 6, 8, 22
+       22, 12, 14, 16, 18, 20, 21
 };
 
 static const char _khmer_syllable_machine_trans_actions[] = {
-       1, 2, 2, 0, 2, 2, 3, 2
-       2, 0, 2, 2, 6, 2, 0, 0, 
-       0, 0, 7, 2, 0, 0, 0, 0, 
-       2, 2, 0, 8, 0, 0, 0, 9
-       2, 0, 0, 2, 0, 10, 0, 0
-       0, 0, 11
+       1, 0, 2, 2, 2, 0, 0, 0
+       2, 0, 2, 0, 2, 2, 3, 0, 
+       4, 5, 2, 0, 0, 0, 2, 0, 
+       2, 0, 2, 4, 4, 8, 9, 0
+       10, 0, 0, 0, 0, 0, 0, 11
+       12, 0, 0, 0, 0, 0, 0
 };
 
 static const char _khmer_syllable_machine_to_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 4, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 6, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0
 };
 
 static const char _khmer_syllable_machine_from_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 5, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 7, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0
+       0
 };
 
 static const unsigned char _khmer_syllable_machine_eof_trans[] = {
-       1, 1, 1, 1, 1, 7, 7, 7, 
-       7, 7, 0, 19, 19, 19, 19, 19, 
-       19, 19, 19, 19, 19, 19, 32, 32, 
-       32, 32, 32, 32, 32, 32, 32, 32, 
-       32, 43, 43, 43
+       1, 1, 1, 1, 1, 1, 1, 1, 
+       1, 1, 1, 15, 18, 18, 18, 18, 
+       18, 18, 18, 18, 18, 18, 0, 33, 
+       33, 33, 33, 33, 33, 33, 33, 40, 
+       41, 41, 41, 41, 41, 41, 40, 41, 
+       41
 };
 
-static const int khmer_syllable_machine_start = 10;
-static const int khmer_syllable_machine_first_final = 10;
+static const int khmer_syllable_machine_start = 22;
+static const int khmer_syllable_machine_first_final = 22;
 static const int khmer_syllable_machine_error = -1;
 
-static const int khmer_syllable_machine_en_main = 10;
+static const int khmer_syllable_machine_en_main = 22;
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -173,11 +242,11 @@ static const int khmer_syllable_machine_en_main = 10;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 181 "hb-ot-shape-complex-khmer-machine.hh"
+#line 250 "hb-ot-shape-complex-khmer-machine.hh"
        {
        cs = khmer_syllable_machine_start;
        ts = 0;
@@ -185,16 +254,15 @@ find_syllables (hb_buffer_t *buffer)
        act = 0;
        }
 
-#line 95 "hb-ot-shape-complex-khmer-machine.rl"
+#line 100 "hb-ot-shape-complex-khmer-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 198 "hb-ot-shape-complex-khmer-machine.hh"
+#line 266 "hb-ot-shape-complex-khmer-machine.hh"
        {
        int _slen;
        int _trans;
@@ -204,11 +272,11 @@ find_syllables (hb_buffer_t *buffer)
                goto _test_eof;
 _resume:
        switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
-       case 5:
+       case 7:
 #line 1 "NONE"
        {ts = p;}
        break;
-#line 212 "hb-ot-shape-complex-khmer-machine.hh"
+#line 280 "hb-ot-shape-complex-khmer-machine.hh"
        }
 
        _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -231,47 +299,63 @@ _eof_trans:
        {te = p+1;}
        break;
        case 8:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-       {te = p+1;{ found_syllable (consonant_syllable); }}
-       break;
-       case 10:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-       {te = p+1;{ found_syllable (broken_cluster); }}
-       break;
-       case 6:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
        {te = p+1;{ found_syllable (non_khmer_cluster); }}
        break;
-       case 7:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+       case 10:
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
        {te = p;p--;{ found_syllable (consonant_syllable); }}
        break;
-       case 9:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
+       case 12:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
        {te = p;p--;{ found_syllable (broken_cluster); }}
        break;
        case 11:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
        {te = p;p--;{ found_syllable (non_khmer_cluster); }}
        break;
        case 1:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
        {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
        break;
-       case 3:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
+       case 5:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
        break;
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
+       case 3:
+#line 1 "NONE"
+       {       switch( act ) {
+       case 2:
+       {{p = ((te))-1;} found_syllable (broken_cluster); }
+       break;
+       case 3:
+       {{p = ((te))-1;} found_syllable (non_khmer_cluster); }
+       break;
+       }
+       }
+       break;
+       case 4:
+#line 1 "NONE"
+       {te = p+1;}
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
+       {act = 2;}
+       break;
+       case 9:
+#line 1 "NONE"
+       {te = p+1;}
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
+       {act = 3;}
+       break;
+#line 350 "hb-ot-shape-complex-khmer-machine.hh"
        }
 
 _again:
        switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
-       case 4:
+       case 6:
 #line 1 "NONE"
        {ts = 0;}
        break;
-#line 275 "hb-ot-shape-complex-khmer-machine.hh"
+#line 359 "hb-ot-shape-complex-khmer-machine.hh"
        }
 
        if ( ++p != pe )
@@ -287,7 +371,7 @@ _again:
 
        }
 
-#line 104 "hb-ot-shape-complex-khmer-machine.rl"
+#line 108 "hb-ot-shape-complex-khmer-machine.rl"
 
 }
 
index 54644d8..4c596ab 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
   machine khmer_syllable_machine;
 # Same order as enum khmer_category_t.  Not sure how to avoid duplication.
 C    = 1;
 V    = 2;
-N    = 3;
 ZWNJ = 5;
 ZWJ  = 6;
-M    = 7;
-SM   = 8;
 PLACEHOLDER = 11;
 DOTTEDCIRCLE = 12;
-RS    = 13;
-Coeng = 14;
-Ra    = 16;
-
-c = (C | Ra | V);              # is_consonant
-n = ((ZWNJ?.RS)? (N.N?)?);     # is_consonant_modifier
-z = ZWJ|ZWNJ;                  # is_joiner
-
-cn = c.n?;
-matra_group = z?.M.N?;
-syllable_tail = (SM.SM?)?;
-
-
-broken_cluster =       n? (Coeng.cn)* matra_group* (Coeng.cn)? syllable_tail;
-consonant_syllable =   (c|PLACEHOLDER|DOTTEDCIRCLE) broken_cluster;
+Coeng= 14;
+Ra   = 16;
+Robatic = 20;
+Xgroup  = 21;
+Ygroup  = 22;
+VAbv = 26;
+VBlw = 27;
+VPre = 28;
+VPst = 29;
+
+c = (C | Ra | V);
+cn = c.((ZWJ|ZWNJ)?.Robatic)?;
+joiner = (ZWJ | ZWNJ);
+xgroup = (joiner*.Xgroup)*;
+ygroup = Ygroup*;
+
+# This grammar was experimentally extracted from what Uniscribe allows.
+
+matra_group = VPre? xgroup VBlw? xgroup (joiner?.VAbv)? xgroup VPst?;
+syllable_tail = xgroup matra_group xgroup (Coeng.c)? ygroup;
+
+
+broken_cluster =       (Coeng.cn)* syllable_tail;
+consonant_syllable =   (cn|PLACEHOLDER|DOTTEDCIRCLE) broken_cluster;
 other =                        any;
 
 main := |*
@@ -75,10 +81,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -86,7 +91,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -97,7 +102,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-khmer-private.hh b/src/hb-ot-shape-complex-khmer-private.hh
deleted file mode 100644 (file)
index f90ef96..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-#define khmer_position() indic_position() /* khmer_position_t */
-
-
-typedef indic_category_t khmer_category_t;
-typedef indic_position_t khmer_position_t;
-
-
-static inline khmer_position_t
-matra_position_khmer (khmer_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:
-      return POS_PRE_M;
-
-    case POS_POST_C:
-    case POS_ABOVE_C:
-    case POS_BELOW_C:
-      return POS_AFTER_POST;
-
-    default:
-      return side;
-  };
-}
-
-static inline bool
-is_consonant_or_vowel (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
-}
-
-static inline bool
-is_coeng (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_Coeng));
-}
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
-  khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
-                    u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
-  {
-    /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
-     * https://github.com/roozbehp/unicode-data/issues/5 */
-    cat = OT_M;
-    pos = POS_ABOVE_C;
-  }
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (u == 0x179Au)
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_khmer (pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  info.khmer_category() = cat;
-  info.khmer_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH */
index 18e3c94..4475ceb 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-khmer-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-khmer.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
  * Khmer shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 khmer_features[] =
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('c','f','a','r'), F_NONE},
+  {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
+  {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
-   * Default Bengali font in Windows for example has intermixed
-   * lookups for init,pres,abvs,blws features.
+   * These features are applied all at once after clearing syllables.
+   */
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
    */
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -79,12 +75,13 @@ enum {
   _ABVS,
   _BLWS,
   _PSTS,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   KHMER_NUM_FEATURES,
-  KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */
+  KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
 };
 
 static void
@@ -92,13 +89,9 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
                 hb_font_t *font,
                 hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                   hb_font_t *font,
-                   hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                 hb_font_t *font,
-                 hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+        hb_font_t *font,
+        hb_buffer_t *buffer);
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan,
                 hb_font_t *font,
@@ -111,46 +104,54 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
 
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
+  map->add_gsub_pause (reorder);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
+  /* Testing suggests that Uniscribe does NOT pause between basic
+   * features.  Test with KhmerUI.ttf and the following three
+   * sequences:
+   *
+   *   U+1789,U+17BC
+   *   U+1789,U+17D2,U+1789
+   *   U+1789,U+17D2,U+1789,U+17BC
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/974
+   */
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
   unsigned int i = 0;
-  map->add_gsub_pause (initial_reordering);
-  for (; i < KHMER_BASIC_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (; i < KHMER_NUM_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
-
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < KHMER_BASIC_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 
   map->add_gsub_pause (clear_syllables);
+
+  for (; i < KHMER_NUM_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 }
 
 static void
 override_features_khmer (hb_ot_shape_planner_t *plan)
 {
+  hb_ot_map_builder_t *map = &plan->map;
+
+  /* Khmer spec has 'clig' as part of required shaping features:
+   * "Apply feature 'clig' to form ligatures that are desired for
+   * typographical correctness.", hence in overrides... */
+  map->enable_feature (HB_TAG('c','l','i','g'));
+
   /* Uniscribe does not apply 'kern' in Khmer. */
   if (hb_options ().uniscribe_bug_compatible)
   {
-    plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL);
+    map->disable_feature (HB_TAG('k','e','r','n'));
   }
 
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  map->disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -158,9 +159,9 @@ struct would_substitute_feature_t
                            &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                               unsigned int          glyphs_count,
-                               hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                        unsigned int          glyphs_count,
+                        hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -176,9 +177,7 @@ struct would_substitute_feature_t
 
 struct khmer_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
     hb_codepoint_t glyph = virama_glyph;
     if (unlikely (virama_glyph == (hb_codepoint_t) -1))
@@ -243,7 +242,6 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
                   hb_font_t                *font HB_UNUSED)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, khmer_position);
 
   /* We cannot setup masks here.  We save information about characters
    * and setup masks later on in a pause-callback. */
@@ -264,159 +262,58 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
     buffer->unsafe_to_break (start, end);
 }
 
-static int
-compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->khmer_position();
-  int b = pb->khmer_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
 
 /* Rules from:
  * https://docs.microsoft.com/en-us/typography/script-development/devanagari */
 
 static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
-                                      hb_face_t *face,
-                                      hb_buffer_t *buffer,
-                                      unsigned int start, unsigned int end)
+reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
+                           hb_face_t *face HB_UNUSED,
+                           hb_buffer_t *buffer,
+                           unsigned int start, unsigned int end)
 {
   const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
-  /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
-
-  /* The first consonant is always the base. */
-  unsigned int base = start;
-  info[base].khmer_position() = POS_BASE_C;
-
-  /* Mark all subsequent consonants as below. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (is_consonant_or_vowel (info[i]))
-      info[i].khmer_position() = POS_BELOW_C;
-
-  /* Mark final consonants.  A final consonant is one appearing after a matra,
-   * like in Khmer. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (info[i].khmer_category() == OT_M) {
-      for (unsigned int j = i + 1; j < end; j++)
-        if (is_consonant_or_vowel (info[j])) {
-         info[j].khmer_position() = POS_FINAL_C;
-         break;
-       }
-      break;
-    }
-
-  /* Attach misc marks to previous char to move with them. */
+  /* Setup masks. */
   {
-    khmer_position_t last_pos = POS_START;
-    for (unsigned int i = start; i < end; i++)
-    {
-      if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
-      {
-       info[i].khmer_position() = last_pos;
-       if (unlikely (info[i].khmer_category() == OT_Coeng &&
-                     info[i].khmer_position() == POS_PRE_M))
-       {
-         /*
-          * Uniscribe doesn't move the Halant with Left Matra.
-          * TEST: U+092B,U+093F,U+094DE
-          * We follow.  This is important for the Sinhala
-          * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
-          * where U+0DD9 is a left matra and U+0DCA is the virama.
-          * We don't want to move the virama with the left matra.
-          * TEST: U+0D9A,U+0DDA
-          */
-         for (unsigned int j = i; j > start; j--)
-           if (info[j - 1].khmer_position() != POS_PRE_M) {
-             info[i].khmer_position() = info[j - 1].khmer_position();
-             break;
-           }
-       }
-      } else if (info[i].khmer_position() != POS_SMVD) {
-        last_pos = (khmer_position_t) info[i].khmer_position();
-      }
-    }
-  }
-  /* For post-base consonants let them own anything before them
-   * since the last consonant or matra. */
-  {
-    unsigned int last = base;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (is_consonant_or_vowel (info[i]))
-      {
-       for (unsigned int j = last + 1; j < i; j++)
-         if (info[j].khmer_position() < POS_SMVD)
-           info[j].khmer_position() = info[i].khmer_position();
-       last = i;
-      } else if (info[i].khmer_category() == OT_M)
-        last = i;
-  }
-
-  {
-    /* Use syllable() for sort accounting temporarily. */
-    unsigned int syllable = info[start].syllable();
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = i - start;
-
-    /* Sit tight, rock 'n roll! */
-    hb_stable_sort (info + start, end - start, compare_khmer_order);
-    /* Find base again */
-    base = end;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].khmer_position() == POS_BASE_C)
-      {
-       base = i;
-       break;
-      }
-
-    /* Note!  syllable() is a one-byte field. */
-    for (unsigned int i = base; i < end; i++)
-      if (info[i].syllable() != 255)
-      {
-       unsigned int max = i;
-       unsigned int j = start + info[i].syllable();
-       while (j != i)
-       {
-         max = MAX (max, j);
-         unsigned int next = start + info[j].syllable();
-         info[j].syllable() = 255; /* So we don't process j later again. */
-         j = next;
-       }
-       if (i != max)
-         buffer->merge_clusters (i, max + 1);
-      }
-
-    /* Put syllable back in. */
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = syllable;
-  }
-
-  /* Setup masks now */
-
-  {
-    hb_mask_t mask;
-
     /* Post-base */
-    mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
-    for (unsigned int i = base + 1; i < end; i++)
+    hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
+    for (unsigned int i = start + 1; i < end; i++)
       info[i].mask  |= mask;
   }
 
-  unsigned int pref_len = 2;
-  if (khmer_plan->mask_array[PREF] && base + pref_len < end)
+  unsigned int num_coengs = 0;
+  for (unsigned int i = start + 1; i < end; i++)
   {
-    /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
-    for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
-      hb_codepoint_t glyphs[2];
-      for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
-      if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
+    /* """
+     * When a COENG + (Cons | IndV) combination are found (and subscript count
+     * is less than two) the character combination is handled according to the
+     * subscript type of the character following the COENG.
+     *
+     * ...
+     *
+     * Subscript Type 2 - The COENG + RO characters are reordered to immediately
+     * before the base glyph. Then the COENG + RO characters are assigned to have
+     * the 'pref' OpenType feature applied to them.
+     * """
+     */
+    if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+    {
+      num_coengs++;
+
+      if (info[i + 1].khmer_category() == OT_Ra)
       {
-       for (unsigned int j = 0; j < pref_len; j++)
-         info[i++].mask |= khmer_plan->mask_array[PREF];
+       for (unsigned int j = 0; j < 2; j++)
+         info[i + j].mask |= khmer_plan->mask_array[PREF];
+
+       /* Move the Coeng,Ro sequence to the start. */
+       buffer->merge_clusters (start, i + 2);
+       hb_glyph_info_t t0 = info[i];
+       hb_glyph_info_t t1 = info[i + 1];
+       memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
+       info[start] = t0;
+       info[start + 1] = t1;
 
        /* Mark the subsequent stuff with 'cfar'.  Used in Khmer.
         * Read the feature spec.
@@ -425,12 +322,22 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
         * U+1784,U+17D2,U+1782,U+17D2,U+179A
         */
        if (khmer_plan->mask_array[CFAR])
-         for (; i < end; i++)
-           info[i].mask |= khmer_plan->mask_array[CFAR];
+         for (unsigned int j = i + 2; j < end; j++)
+           info[j].mask |= khmer_plan->mask_array[CFAR];
 
-       break;
+       num_coengs = 2; /* Done. */
       }
     }
+
+    /* Reorder left matra piece. */
+    else if (info[i].khmer_category() == OT_VPre)
+    {
+      /* Move to the start. */
+      buffer->merge_clusters (start, i + 1);
+      hb_glyph_info_t t = info[i];
+      memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
+      info[start] = t;
+    }
   }
 }
 
@@ -445,7 +352,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
   {
     case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
     case consonant_syllable:
-     initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+     reorder_consonant_syllable (plan, face, buffer, start, end);
      break;
 
     case non_khmer_cluster:
@@ -510,263 +417,22 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                   hb_font_t *font,
-                   hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+        hb_font_t *font,
+        hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                          hb_buffer_t *buffer,
-                          unsigned int start, unsigned int end)
-{
-  const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-
-  /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiple substitutions happened prior to this
-   * phase, and that might have messed up our properties.  Recover
-   * from a particular case of that where we're fairly sure that a
-   * class of OT_Coeng is desired but has been lost. */
-  if (khmer_plan->virama_glyph)
-  {
-    unsigned int virama_glyph = khmer_plan->virama_glyph;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].codepoint == virama_glyph &&
-         _hb_glyph_info_ligated (&info[i]) &&
-         _hb_glyph_info_multiplied (&info[i]))
-      {
-        /* This will make sure that this glyph passes is_coeng() test. */
-       info[i].khmer_category() = OT_Coeng;
-       _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
-      }
-  }
-
-
-  /* 4. Final reordering:
-   *
-   * After the localized forms and basic shaping forms GSUB features have been
-   * applied (see below), the shaping engine performs some final glyph
-   * reordering before applying all the remaining font features to the entire
-   * syllable.
-   */
-
-  bool try_pref = !!khmer_plan->mask_array[PREF];
-
-  /* Find base again */
-  unsigned int base;
-  for (base = start; base < end; base++)
-    if (info[base].khmer_position() >= POS_BASE_C)
-    {
-      if (try_pref && base + 1 < end)
-      {
-       for (unsigned int i = base + 1; i < end; i++)
-         if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-         {
-           if (!(_hb_glyph_info_substituted (&info[i]) &&
-                 _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
-           {
-             /* Ok, this was a 'pref' candidate but didn't form any.
-              * Base is around here... */
-             base = i;
-             while (base < end && is_coeng (info[base]))
-               base++;
-             info[base].khmer_position() = POS_BASE_C;
-
-             try_pref = false;
-           }
-           break;
-         }
-      }
-
-      if (start < base && info[base].khmer_position() > POS_BASE_C)
-        base--;
-      break;
-    }
-  if (base == end && start < base &&
-      is_one_of (info[base - 1], FLAG (OT_ZWJ)))
-    base--;
-  if (base < end)
-    while (start < base &&
-          is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
-      base--;
-
-
-  /*   o Reorder matras:
-   *
-   *     If a pre-base matra character had been reordered before applying basic
-   *     features, the glyph can be moved closer to the main consonant based on
-   *     whether half-forms had been formed. Actual position for the matra is
-   *     defined as “after last standalone halant glyph, after initial matra
-   *     position and before the main consonant”. If ZWJ or ZWNJ follow this
-   *     halant, position is moved after it.
-   */
-
-  if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
-  {
-    /* If we lost track of base, alas, position before last thingy. */
-    unsigned int new_pos = base == end ? base - 2 : base - 1;
-
-    while (new_pos > start &&
-          !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
-      new_pos--;
-
-    /* If we found no Halant we are done.
-     * Otherwise only proceed if the Halant does
-     * not belong to the Matra itself! */
-    if (is_coeng (info[new_pos]) &&
-       info[new_pos].khmer_position() != POS_PRE_M)
-    {
-      /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-      if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
-       new_pos++;
-    }
-    else
-      new_pos = start; /* No move. */
-
-    if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
-    {
-      /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_pos; i > start; i--)
-       if (info[i - 1].khmer_position () == POS_PRE_M)
-       {
-         unsigned int old_pos = i - 1;
-         if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
-           base--;
-
-         hb_glyph_info_t tmp = info[old_pos];
-         memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
-         info[new_pos] = tmp;
-
-         /* Note: this merge_clusters() is intentionally *after* the reordering.
-          * Indic matra reordering is special and tricky... */
-         buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
-         new_pos--;
-       }
-    } else {
-      for (unsigned int i = start; i < base; i++)
-       if (info[i].khmer_position () == POS_PRE_M) {
-         buffer->merge_clusters (i, MIN (end, base + 1));
-         break;
-       }
-    }
-  }
-
-
-  /*   o Reorder pre-base-reordering consonants:
-   *
-   *     If a pre-base-reordering consonant is found, reorder it according to
-   *     the following rules:
-   */
-
-  if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
-  {
-    for (unsigned int i = base + 1; i < end; i++)
-      if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-      {
-       /*       1. Only reorder a glyph produced by substitution during application
-        *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-        *          the feature generally but block it in certain contexts.)
-        */
-        /* Note: We just check that something got substituted.  We don't check that
-        * the <pref> feature actually did it...
-        *
-        * Reorder pref only if it ligated. */
-       if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
-       {
-         /*
-          *       2. Try to find a target position the same way as for pre-base matra.
-          *          If it is found, reorder pre-base consonant glyph.
-          *
-          *       3. If position is not found, reorder immediately before main
-          *          consonant.
-          */
-
-         unsigned int new_pos = base;
-         while (new_pos > start &&
-                !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
-           new_pos--;
-
-         /* In Khmer coeng model, a H,Ra can go *after* matras.  If it goes after a
-          * split matra, it should be reordered to *before* the left part of such matra. */
-         if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
-         {
-           unsigned int old_pos = i;
-           for (unsigned int j = base + 1; j < old_pos; j++)
-             if (info[j].khmer_category() == OT_M)
-             {
-               new_pos--;
-               break;
-             }
-         }
-
-         if (new_pos > start && is_coeng (info[new_pos - 1]))
-         {
-           /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-           if (new_pos < end && is_joiner (info[new_pos]))
-             new_pos++;
-         }
-
-         {
-           unsigned int old_pos = i;
-
-           buffer->merge_clusters (new_pos, old_pos + 1);
-           hb_glyph_info_t tmp = info[old_pos];
-           memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-           info[new_pos] = tmp;
-
-           if (new_pos <= base && base < old_pos)
-             base++;
-         }
-       }
-
-        break;
-      }
-  }
-
-
-  /*
-   * Finish off the clusters and go home!
-   */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
-     * This means, half forms are submerged into the main consonant's cluster.
-     * This is unnecessary, and makes cursor positioning harder, but that's what
-     * Uniscribe does. */
-    buffer->merge_clusters (start, end);
-  }
-}
-
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                 hb_font_t *font HB_UNUSED,
-                 hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  if (unlikely (!count)) return;
-
-  foreach_syllable (buffer, start, end)
-    final_reordering_syllable (plan, buffer, start, end);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
 }
 
-
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
                 hb_font_t *font HB_UNUSED,
@@ -828,7 +494,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
   decompose_khmer,
   compose_khmer,
   setup_masks_khmer,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
diff --git a/src/hb-ot-shape-complex-khmer.hh b/src/hb-ot-shape-complex-khmer.hh
new file mode 100644 (file)
index 0000000..6222945
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
+#define HB_OT_SHAPE_COMPLEX_KHMER_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define khmer_category() indic_category() /* khmer_category_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum khmer_category_t
+{
+  OT_Robatic = 20,
+  OT_Xgroup  = 21,
+  OT_Ygroup  = 22,
+
+  OT_VAbv    = 26,
+  OT_VBlw    = 27,
+  OT_VPre    = 28,
+  OT_VPst    = 29,
+};
+
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   *
+   * These categories are experimentally extracted from what Uniscribe allows.
+   */
+  switch (u)
+  {
+    case 0x179Au:
+      cat = (khmer_category_t) OT_Ra;
+      break;
+
+    case 0x17CCu:
+    case 0x17C9u:
+    case 0x17CAu:
+      cat = OT_Robatic;
+      break;
+
+    case 0x17C6u:
+    case 0x17CBu:
+    case 0x17CDu:
+    case 0x17CEu:
+    case 0x17CFu:
+    case 0x17D0u:
+    case 0x17D1u:
+      cat = OT_Xgroup;
+      break;
+
+    case 0x17C7u:
+    case 0x17C8u:
+    case 0x17DDu:
+    case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
+      cat = OT_Ygroup;
+      break;
+  }
+
+  /*
+   * Re-assign position.
+   */
+  if (cat == (khmer_category_t) OT_M)
+    switch ((int) pos)
+    {
+      case POS_PRE_C:  cat = OT_VPre; break;
+      case POS_BELOW_C:        cat = OT_VBlw; break;
+      case POS_ABOVE_C:        cat = OT_VAbv; break;
+      case POS_POST_C: cat = OT_VPst; break;
+      default: assert (0);
+    };
+
+  info.khmer_category() = cat;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
index fb67dd4..0c19e4f 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
@@ -283,10 +283,9 @@ static const int myanmar_syllable_machine_en_main = 0;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -294,11 +293,11 @@ static const int myanmar_syllable_machine_en_main = 0;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 302 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
        {
        cs = myanmar_syllable_machine_start;
        ts = 0;
@@ -306,16 +305,15 @@ find_syllables (hb_buffer_t *buffer)
        act = 0;
        }
 
-#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 319 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
        {
        int _slen;
        int _trans;
@@ -329,7 +327,7 @@ _resume:
 #line 1 "NONE"
        {ts = p;}
        break;
-#line 333 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
        }
 
        _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -379,7 +377,7 @@ _eof_trans:
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
        {te = p;p--;{ found_syllable (non_myanmar_cluster); }}
        break;
-#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
        }
 
 _again:
@@ -388,7 +386,7 @@ _again:
 #line 1 "NONE"
        {ts = 0;}
        break;
-#line 392 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
        }
 
        if ( ++p != pe )
@@ -404,7 +402,7 @@ _again:
 
        }
 
-#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
index 0cd84fa..7845a86 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
   machine myanmar_syllable_machine;
@@ -95,10 +95,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -106,7 +105,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -117,7 +116,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-myanmar-private.hh b/src/hb-ot-shape-complex-myanmar-private.hh
deleted file mode 100644 (file)
index 14d011d..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
-  OT_As  = 18,  /* Asat */
-  OT_D0  = 20, /* Digit zero */
-  OT_DB  = OT_N, /* Dot below */
-  OT_GB  = OT_PLACEHOLDER,
-  OT_MH  = 21, /* Various consonant medial types */
-  OT_MR  = 22, /* Various consonant medial types */
-  OT_MW  = 23, /* Various consonant medial types */
-  OT_MY  = 24, /* Various consonant medial types */
-  OT_PT  = 25, /* Pwo and other tones */
-  OT_VAbv = 26,
-  OT_VBlw = 27,
-  OT_VPre = 28,
-  OT_VPst = 29,
-  OT_VS   = 30, /* Variation selectors */
-  OT_P    = 31, /* Punctuation */
-  OT_D    = 32, /* Digits except zero */
-};
-
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-  /* Myanmar
-   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
-   */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
-    cat = (indic_category_t) OT_VS;
-
-  switch (u)
-  {
-    case 0x104Eu:
-      cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
-      break;
-
-    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
-    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
-    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
-    case 0x25FEu:
-      cat = (indic_category_t) OT_GB;
-      break;
-
-    case 0x1004u: case 0x101Bu: case 0x105Au:
-      cat = (indic_category_t) OT_Ra;
-      break;
-
-    case 0x1032u: case 0x1036u:
-      cat = (indic_category_t) OT_A;
-      break;
-
-    case 0x1039u:
-      cat = (indic_category_t) OT_H;
-      break;
-
-    case 0x103Au:
-      cat = (indic_category_t) OT_As;
-      break;
-
-    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
-    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
-    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
-    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
-    case 0x1097u: case 0x1098u: case 0x1099u:
-      cat = (indic_category_t) OT_D;
-      break;
-
-    case 0x1040u:
-      cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
-      break;
-
-    case 0x103Eu: case 0x1060u:
-      cat = (indic_category_t) OT_MH;
-      break;
-
-    case 0x103Cu:
-      cat = (indic_category_t) OT_MR;
-      break;
-
-    case 0x103Du: case 0x1082u:
-      cat = (indic_category_t) OT_MW;
-      break;
-
-    case 0x103Bu: case 0x105Eu: case 0x105Fu:
-      cat = (indic_category_t) OT_MY;
-      break;
-
-    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
-    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
-      cat = (indic_category_t) OT_PT;
-      break;
-
-    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
-    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
-    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
-      cat = (indic_category_t) OT_SM;
-      break;
-
-    case 0x104Au: case 0x104Bu:
-      cat = (indic_category_t) OT_P;
-      break;
-
-    case 0xAA74u: case 0xAA75u: case 0xAA76u:
-      /* https://github.com/roozbehp/unicode-data/issues/3 */
-      cat = (indic_category_t) OT_C;
-      break;
-  }
-
-  if (cat == OT_M)
-  {
-    switch ((int) pos)
-    {
-      case POS_PRE_C:  cat = (indic_category_t) OT_VPre;
-                       pos = POS_PRE_M;                  break;
-      case POS_ABOVE_C:        cat = (indic_category_t) OT_VAbv; break;
-      case POS_BELOW_C:        cat = (indic_category_t) OT_VBlw; break;
-      case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
-    }
-  }
-
-  info.myanmar_category() = (myanmar_category_t) cat;
-  info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH */
index e4214b8..8fdf2f4 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-myanmar-private.hh"
+#include "hb-ot-shape-complex-myanmar.hh"
 
 
 /*
@@ -36,7 +36,7 @@ basic_features[] =
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
   HB_TAG('r','p','h','f'),
   HB_TAG('p','r','e','f'),
@@ -48,13 +48,20 @@ other_features[] =
 {
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after clearing syllables.
    */
   HB_TAG('p','r','e','s'),
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
    * features.  The released Windows 8 version of the font (as well
@@ -73,13 +80,13 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
                 hb_font_t *font,
                 hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                   hb_font_t *font,
-                   hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+        hb_font_t *font,
+        hb_buffer_t *buffer);
 static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                 hb_font_t *font,
-                 hb_buffer_t *buffer);
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                hb_font_t *font,
+                hb_buffer_t *buffer);
 
 static void
 collect_features_myanmar (hb_ot_shape_planner_t *plan)
@@ -89,27 +96,33 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+
 
+  map->add_gsub_pause (reorder);
 
-  map->add_gsub_pause (initial_reordering);
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
   {
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
     map->add_gsub_pause (nullptr);
   }
-  map->add_gsub_pause (final_reordering);
+
+  map->add_gsub_pause (clear_syllables);
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 static void
 override_features_myanmar (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
@@ -261,8 +274,8 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
 }
 
 static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                            hb_face_t *face,
+initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                            hb_face_t *face HB_UNUSED,
                             hb_buffer_t *buffer,
                             unsigned int start, unsigned int end)
 {
@@ -330,72 +343,71 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                   hb_font_t *font,
-                   hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+        hb_font_t *font,
+        hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
+
+  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
 }
 
 static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                 hb_font_t *font HB_UNUSED,
-                 hb_buffer_t *buffer)
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                hb_font_t *font HB_UNUSED,
+                hb_buffer_t *buffer)
 {
   hb_glyph_info_t *info = buffer->info;
   unsigned int count = buffer->len;
-
-  /* Zero syllables now... */
   for (unsigned int i = 0; i < count; i++)
     info[i].syllable() = 0;
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
 }
 
 
-/* Uniscribe seems to have a shaper for 'mymr' that is like the
- * generic shaper, except that it zeros mark advances GDEF_LATE. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
+const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
 {
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
+  collect_features_myanmar,
+  override_features_myanmar,
   nullptr, /* data_create */
   nullptr, /* data_destroy */
   nullptr, /* preprocess_text */
   nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   nullptr, /* decompose */
   nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  setup_masks_myanmar,
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+  false, /* fallback_position */
 };
 
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
+
+/* Ugly Zawgyi encoding.
+ * Disable all auto processing.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162 */
+const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
 {
-  collect_features_myanmar,
-  override_features_myanmar,
+  nullptr, /* collect_features */
+  nullptr, /* override_features */
   nullptr, /* data_create */
   nullptr, /* data_destroy */
   nullptr, /* preprocess_text */
   nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
   nullptr, /* decompose */
   nullptr, /* compose */
-  setup_masks_myanmar,
-  nullptr, /* disable_otl */
+  nullptr, /* setup_masks */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
diff --git a/src/hb-ot-shape-complex-myanmar.hh b/src/hb-ot-shape-complex-myanmar.hh
new file mode 100644 (file)
index 0000000..3e9537a
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define myanmar_category() indic_category() /* myanmar_category_t */
+#define myanmar_position() indic_position() /* myanmar_position_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum myanmar_category_t {
+  OT_As  = 18,  /* Asat */
+  OT_D0  = 20, /* Digit zero */
+  OT_DB  = OT_N, /* Dot below */
+  OT_GB  = OT_PLACEHOLDER,
+  OT_MH  = 21, /* Various consonant medial types */
+  OT_MR  = 22, /* Various consonant medial types */
+  OT_MW  = 23, /* Various consonant medial types */
+  OT_MY  = 24, /* Various consonant medial types */
+  OT_PT  = 25, /* Pwo and other tones */
+  OT_VAbv = 26,
+  OT_VBlw = 27,
+  OT_VPre = 28,
+  OT_VPst = 29,
+  OT_VS   = 30, /* Variation selectors */
+  OT_P    = 31, /* Punctuation */
+  OT_D    = 32, /* Digits except zero */
+};
+
+
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  unsigned int cat = type & 0x7Fu;
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+  /* Myanmar
+   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
+   */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
+    cat = OT_VS;
+
+  switch (u)
+  {
+    case 0x104Eu:
+      cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
+      break;
+
+    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
+    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
+    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
+    case 0x25FEu:
+      cat = OT_GB;
+      break;
+
+    case 0x1004u: case 0x101Bu: case 0x105Au:
+      cat = OT_Ra;
+      break;
+
+    case 0x1032u: case 0x1036u:
+      cat = OT_A;
+      break;
+
+    case 0x1039u:
+      cat = OT_H;
+      break;
+
+    case 0x103Au:
+      cat = OT_As;
+      break;
+
+    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
+    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
+    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
+    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
+    case 0x1097u: case 0x1098u: case 0x1099u:
+      cat = OT_D;
+      break;
+
+    case 0x1040u:
+      cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
+      break;
+
+    case 0x103Eu: case 0x1060u:
+      cat = OT_MH;
+      break;
+
+    case 0x103Cu:
+      cat = OT_MR;
+      break;
+
+    case 0x103Du: case 0x1082u:
+      cat = OT_MW;
+      break;
+
+    case 0x103Bu: case 0x105Eu: case 0x105Fu:
+      cat = OT_MY;
+      break;
+
+    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
+    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
+      cat = OT_PT;
+      break;
+
+    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
+    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
+    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
+      cat = OT_SM;
+      break;
+
+    case 0x104Au: case 0x104Bu:
+      cat = OT_P;
+      break;
+
+    case 0xAA74u: case 0xAA75u: case 0xAA76u:
+      /* https://github.com/roozbehp/unicode-data/issues/3 */
+      cat = OT_C;
+      break;
+  }
+
+  if (cat == OT_M)
+  {
+    switch ((int) pos)
+    {
+      case POS_PRE_C:  cat = OT_VPre;
+                       pos = POS_PRE_M; break;
+      case POS_ABOVE_C:        cat = OT_VAbv;   break;
+      case POS_BELOW_C:        cat = OT_VBlw;   break;
+      case POS_POST_C: cat = OT_VPst;   break;
+    }
+  }
+
+  info.myanmar_category() = cat;
+  info.myanmar_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh
deleted file mode 100644 (file)
index ed6849b..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright © 2010,2011,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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-
-
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_0()     var2.u8[2]
-#define complex_var_u8_1()     var2.u8[3]
-
-
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
-
-enum hb_ot_shape_zero_width_marks_type_t {
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
-};
-
-
-/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
-  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
-  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
-  /* ^--- Add new shapers here */
-
-
-struct hb_ot_complex_shaper_t
-{
-  /* collect_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to add their features and callbacks.
-   * May be nullptr.
-   */
-  void (*collect_features) (hb_ot_shape_planner_t *plan);
-
-  /* override_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to override features and add callbacks after
-   * common features are added.
-   * May be nullptr.
-   */
-  void (*override_features) (hb_ot_shape_planner_t *plan);
-
-
-  /* data_create()
-   * Called at the end of shape_plan().
-   * Whatever shapers return will be accessible through plan->data later.
-   * If nullptr is returned, means a plan failure.
-   */
-  void *(*data_create) (const hb_ot_shape_plan_t *plan);
-
-  /* data_destroy()
-   * Called when the shape_plan is being destroyed.
-   * plan->data is passed here for destruction.
-   * If nullptr is returned, means a plan failure.
-   * May be nullptr.
-   */
-  void (*data_destroy) (void *data);
-
-
-  /* preprocess_text()
-   * Called during shape().
-   * Shapers can use to modify text before shaping starts.
-   * May be nullptr.
-   */
-  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
-                          hb_buffer_t              *buffer,
-                          hb_font_t                *font);
-
-  /* postprocess_glyphs()
-   * Called during shape().
-   * Shapers can use to modify glyphs after shaping ends.
-   * May be nullptr.
-   */
-  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
-                             hb_buffer_t              *buffer,
-                             hb_font_t                *font);
-
-
-  hb_ot_shape_normalization_mode_t normalization_preference;
-
-  /* decompose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                    hb_codepoint_t  ab,
-                    hb_codepoint_t *a,
-                    hb_codepoint_t *b);
-
-  /* compose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                  hb_codepoint_t  a,
-                  hb_codepoint_t  b,
-                  hb_codepoint_t *ab);
-
-  /* setup_masks()
-   * Called during shape().
-   * Shapers should use map to get feature masks and set on buffer.
-   * Shapers may NOT modify characters.
-   * May be nullptr.
-   */
-  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
-                      hb_buffer_t              *buffer,
-                      hb_font_t                *font);
-
-  /* disable_otl()
-   * Called during shape().
-   * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
-   * and fallback operations used.
-   * May be nullptr.
-   */
-  bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
-
-  /* reorder_marks()
-   * Called during shape().
-   * Shapers can use to modify ordering of combining marks.
-   * May be nullptr.
-   */
-  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
-                        hb_buffer_t              *buffer,
-                        unsigned int              start,
-                        unsigned int              end);
-
-  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
-
-  bool fallback_position;
-};
-
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
-
-
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
-{
-  switch ((hb_tag_t) planner->props.script)
-  {
-    default:
-      return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_MONGOLIAN:
-    case HB_SCRIPT_SYRIAC:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:
-    case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_HANIFI_ROHINGYA:
-    case HB_SCRIPT_SOGDIAN:
-
-      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
-       * This is because we do fallback shaping for Arabic script (and not others).
-       * But note that Arabic shaping is applicable only to horizontal layout; for
-       * vertical text, just use the generic shaper instead. */
-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-          planner->props.script == HB_SCRIPT_ARABIC) &&
-         HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
-       return &_hb_ot_complex_shaper_arabic;
-      else
-       return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_THAI:
-    case HB_SCRIPT_LAO:
-
-      return &_hb_ot_complex_shaper_thai;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HANGUL:
-
-      return &_hb_ot_complex_shaper_hangul;
-
-
-    /* Unicode-2.0 additions */
-    case HB_SCRIPT_TIBETAN:
-
-      return &_hb_ot_complex_shaper_tibetan;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HEBREW:
-
-      return &_hb_ot_complex_shaper_hebrew;
-
-
-    /* ^--- Add new shapers here */
-
-#if 0
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_NEW_TAI_LUE:
-#endif
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_BENGALI:
-    case HB_SCRIPT_DEVANAGARI:
-    case HB_SCRIPT_GUJARATI:
-    case HB_SCRIPT_GURMUKHI:
-    case HB_SCRIPT_KANNADA:
-    case HB_SCRIPT_MALAYALAM:
-    case HB_SCRIPT_ORIYA:
-    case HB_SCRIPT_TAMIL:
-    case HB_SCRIPT_TELUGU:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_SINHALA:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-         planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-       return &_hb_ot_complex_shaper_default;
-      else
-       return &_hb_ot_complex_shaper_indic;
-
-    case HB_SCRIPT_KHMER:
-      /* A number of Khmer fonts in the wild don't have a 'pref' feature,
-       * and as such won't shape properly via the Indic shaper;
-       * however, they typically have 'liga' / 'clig' features that implement
-       * the necessary "reordering" by means of ligature substitutions.
-       * So we send such pref-less fonts through the generic shaper instead. */
-      if (planner->map.found_script[0] &&
-         hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
-                                             planner->map.script_index[0],
-                                             planner->map.language_index[0],
-                                             HB_TAG ('p','r','e','f'),
-                                             nullptr))
-       return &_hb_ot_complex_shaper_khmer;
-      else
-       return &_hb_ot_complex_shaper_default;
-
-    case HB_SCRIPT_MYANMAR:
-      if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
-       return &_hb_ot_complex_shaper_myanmar;
-      else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
-       return &_hb_ot_complex_shaper_myanmar_old;
-      else
-       return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-2.0 additions */
-    //case HB_SCRIPT_TIBETAN:
-
-    /* Unicode-3.0 additions */
-    //case HB_SCRIPT_MONGOLIAN:
-    //case HB_SCRIPT_SINHALA:
-
-    /* Unicode-3.2 additions */
-    case HB_SCRIPT_BUHID:
-    case HB_SCRIPT_HANUNOO:
-    case HB_SCRIPT_TAGALOG:
-    case HB_SCRIPT_TAGBANWA:
-
-    /* Unicode-4.0 additions */
-    case HB_SCRIPT_LIMBU:
-    case HB_SCRIPT_TAI_LE:
-
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_BUGINESE:
-    case HB_SCRIPT_KHAROSHTHI:
-    case HB_SCRIPT_SYLOTI_NAGRI:
-    case HB_SCRIPT_TIFINAGH:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_BALINESE:
-    //case HB_SCRIPT_NKO:
-    //case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_CHAM:
-    case HB_SCRIPT_KAYAH_LI:
-    case HB_SCRIPT_LEPCHA:
-    case HB_SCRIPT_REJANG:
-    case HB_SCRIPT_SAURASHTRA:
-    case HB_SCRIPT_SUNDANESE:
-
-    /* Unicode-5.2 additions */
-    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
-    case HB_SCRIPT_JAVANESE:
-    case HB_SCRIPT_KAITHI:
-    case HB_SCRIPT_MEETEI_MAYEK:
-    case HB_SCRIPT_TAI_THAM:
-    case HB_SCRIPT_TAI_VIET:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_BATAK:
-    case HB_SCRIPT_BRAHMI:
-    //case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-6.1 additions */
-    case HB_SCRIPT_CHAKMA:
-    case HB_SCRIPT_SHARADA:
-    case HB_SCRIPT_TAKRI:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_DUPLOYAN:
-    case HB_SCRIPT_GRANTHA:
-    case HB_SCRIPT_KHOJKI:
-    case HB_SCRIPT_KHUDAWADI:
-    case HB_SCRIPT_MAHAJANI:
-    //case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_MODI:
-    case HB_SCRIPT_PAHAWH_HMONG:
-    //case HB_SCRIPT_PSALTER_PAHLAVI:
-    case HB_SCRIPT_SIDDHAM:
-    case HB_SCRIPT_TIRHUTA:
-
-    /* Unicode-8.0 additions */
-    case HB_SCRIPT_AHOM:
-    //case HB_SCRIPT_MULTANI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_BHAIKSUKI:
-    case HB_SCRIPT_MARCHEN:
-    case HB_SCRIPT_NEWA:
-
-    /* Unicode-10.0 additions */
-    case HB_SCRIPT_MASARAM_GONDI:
-    case HB_SCRIPT_SOYOMBO:
-    case HB_SCRIPT_ZANABAZAR_SQUARE:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_DOGRA:
-    case HB_SCRIPT_GUNJALA_GONDI:
-    case HB_SCRIPT_MAKASAR:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-         planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-       return &_hb_ot_complex_shaper_default;
-      else
-       return &_hb_ot_complex_shaper_use;
-  }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
index 02d78ac..650c980 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Thai / Lao shaper */
@@ -324,9 +324,9 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
     }
 
     /* Is SARA AM. Decompose and reorder. */
-    hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
-                                   hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
-    buffer->replace_glyphs (1, 2, decomposed);
+    hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
+    _hb_glyph_info_set_continuation (&nikhahit);
+    buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u));
     if (unlikely (!buffer->successful))
       return;
 
@@ -376,7 +376,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   false,/* fallback_position */
diff --git a/src/hb-ot-shape-complex-tibetan.cc b/src/hb-ot-shape-complex-tibetan.cc
deleted file mode 100644 (file)
index eaac0bf..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-static const hb_tag_t tibetan_features[] =
-{
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-  HB_TAG_NONE
-};
-
-static void
-collect_features_tibetan (hb_ot_shape_planner_t *plan)
-{
-  for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
-    plan->map.add_global_bool_feature (*script_features);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
-{
-  collect_features_tibetan,
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
index 0ec805a..c9410e4 100644 (file)
 #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 38 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-       12u, 12u, 1u, 15u, 1u, 1u, 12u, 12u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u, 
-       1u, 15u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 
-       8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
-       8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 
-       8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 
-       8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
-       8u, 39u, 1u, 15u, 12u, 12u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, 42u, 42u, 
-       1u, 5u, 0
+       12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u,
+       1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
+       8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+       8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u,
+       8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u,
+       8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+       8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u,
+       41u, 42u, 42u, 42u, 1u, 5u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-       1, 15, 1, 1, 44, 1, 32, 32, 
-       15, 1, 32, 32, 32, 19, 19, 19, 
-       32, 32, 32, 32, 32, 32, 32, 32, 
-       32, 32, 32, 32, 9, 1, 1, 32, 
-       32, 32, 32, 19, 19, 19, 32, 32, 
-       32, 32, 32, 32, 32, 32, 32, 32, 
-       32, 15, 1, 39, 32, 22, 2, 1, 
-       5
+       33, 15, 1, 33, 45, 1, 37, 37,
+       15, 1, 37, 37, 32, 19, 19, 19,
+       32, 32, 32, 37, 37, 37, 37, 37,
+       37, 37, 37, 39, 37, 9, 1, 1,
+       37, 37, 37, 32, 19, 19, 19, 32,
+       32, 32, 37, 37, 37, 37, 37, 37,
+       37, 37, 39, 15, 33, 44, 37, 22,
+       2, 1, 5
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-       0, 2, 18, 20, 22, 67, 69, 102, 
-       135, 151, 153, 186, 219, 252, 272, 292, 
-       312, 345, 378, 411, 444, 477, 510, 543, 
-       576, 609, 642, 675, 708, 718, 720, 722, 
-       755, 788, 821, 854, 874, 894, 914, 947, 
-       980, 1013, 1046, 1079, 1112, 1145, 1178, 1211, 
-       1244, 1277, 1293, 1295, 1335, 1368, 1391, 1394, 
-       1396
+       0, 34, 50, 52, 86, 132, 134, 172,
+       210, 226, 228, 266, 304, 337, 357, 377,
+       397, 430, 463, 496, 534, 572, 610, 648,
+       686, 724, 762, 800, 840, 878, 888, 890,
+       892, 930, 968, 1006, 1039, 1059, 1079, 1099,
+       1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388,
+       1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675,
+       1698, 1701, 1703
 };
 
 static const char _use_syllable_machine_indicies[] = {
+       1, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
        1, 0, 3, 2, 2, 2, 2, 2, 
        2, 2, 2, 2, 2, 2, 2, 2, 
-       4, 2, 3, 2, 6, 5, 7, 8, 
+       4, 2, 3, 2, 6, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 6, 5, 7, 8,
        9, 7, 10, 8, 9, 9, 11, 9, 
        9, 3, 12, 9, 9, 13, 7, 7, 
        14, 15, 9, 9, 16, 17, 18, 19, 
        20, 21, 22, 16, 23, 24, 25, 26, 
        27, 28, 9, 29, 30, 31, 9, 9, 
-       9, 32, 9, 34, 33, 36, 35, 35, 
-       37, 1, 35, 35, 38, 35, 35, 35, 
-       35, 35, 39, 40, 41, 42, 43, 44, 
-       45, 46, 40, 47, 39, 48, 49, 50, 
-       51, 35, 52, 53, 54, 35, 36, 35, 
-       35, 37, 1, 35, 35, 38, 35, 35, 
-       35, 35, 35, 55, 40, 41, 42, 43, 
-       44, 45, 46, 40, 47, 48, 48, 49, 
-       50, 51, 35, 52, 53, 54, 35, 37, 
-       56, 56, 56, 56, 56, 56, 56, 56, 
-       56, 56, 56, 56, 56, 57, 56, 37, 
-       56, 36, 35, 35, 37, 1, 35, 35, 
-       38, 35, 35, 35, 35, 35, 35, 40, 
-       41, 42, 43, 44, 45, 46, 40, 47, 
-       48, 48, 49, 50, 51, 35, 52, 53, 
-       54, 35, 36, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       40, 41, 42, 43, 44, 35, 35, 35, 
-       35, 35, 35, 49, 50, 51, 35, 52, 
-       53, 54, 35, 36, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 41, 42, 43, 44, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       52, 53, 54, 35, 36, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 42, 43, 44, 35, 
-       36, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 43, 44, 35, 36, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 44, 35, 
-       36, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       42, 43, 44, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 52, 53, 54, 
-       35, 36, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 42, 43, 44, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 53, 
-       54, 35, 36, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 42, 43, 44, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 54, 35, 36, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 41, 42, 43, 44, 35, 35, 
-       35, 35, 35, 35, 49, 50, 51, 35, 
-       52, 53, 54, 35, 36, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 41, 42, 43, 44, 35, 
-       35, 35, 35, 35, 35, 35, 50, 51, 
-       35, 52, 53, 54, 35, 36, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 41, 42, 43, 44, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       51, 35, 52, 53, 54, 35, 36, 35, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 40, 41, 42, 43, 
-       44, 35, 46, 40, 35, 35, 35, 49, 
-       50, 51, 35, 52, 53, 54, 35, 36, 
-       35, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 40, 41, 42, 
-       43, 44, 35, 58, 40, 35, 35, 35, 
-       49, 50, 51, 35, 52, 53, 54, 35, 
-       36, 35, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 40, 41, 
-       42, 43, 44, 35, 35, 40, 35, 35, 
-       35, 49, 50, 51, 35, 52, 53, 54, 
-       35, 36, 35, 35, 35, 35, 35, 35, 
-       35, 35, 35, 35, 35, 35, 35, 40, 
-       41, 42, 43, 44, 45, 46, 40, 35, 
-       35, 35, 49, 50, 51, 35, 52, 53, 
-       54, 35, 36, 35, 35, 37, 1, 35, 
-       35, 38, 35, 35, 35, 35, 35, 35, 
-       40, 41, 42, 43, 44, 45, 46, 40, 
-       47, 35, 48, 49, 50, 51, 35, 52, 
-       53, 54, 35, 36, 35, 35, 37, 1, 
-       35, 35, 38, 35, 35, 35, 35, 35, 
-       35, 40, 41, 42, 43, 44, 45, 46, 
-       40, 47, 39, 48, 49, 50, 51, 35, 
-       52, 53, 54, 35, 60, 59, 59, 59, 
-       59, 59, 59, 59, 61, 59, 10, 62, 
-       60, 59, 11, 63, 63, 3, 6, 63, 
-       63, 64, 63, 63, 63, 63, 63, 65, 
+       9, 32, 33, 9, 35, 34, 37, 36,
+       36, 38, 1, 36, 36, 39, 36, 36,
+       36, 36, 36, 40, 41, 42, 43, 44,
+       45, 46, 47, 41, 48, 40, 49, 50,
+       51, 52, 36, 53, 54, 55, 36, 36,
+       36, 36, 56, 36, 37, 36, 36, 38,
+       1, 36, 36, 39, 36, 36, 36, 36,
+       36, 57, 41, 42, 43, 44, 45, 46,
+       47, 41, 48, 49, 49, 50, 51, 52,
+       36, 53, 54, 55, 36, 36, 36, 36,
+       56, 36, 38, 58, 58, 58, 58, 58,
+       58, 58, 58, 58, 58, 58, 58, 58,
+       59, 58, 38, 58, 37, 36, 36, 38,
+       1, 36, 36, 39, 36, 36, 36, 36,
+       36, 36, 41, 42, 43, 44, 45, 46,
+       47, 41, 48, 49, 49, 50, 51, 52,
+       36, 53, 54, 55, 36, 36, 36, 36,
+       56, 36, 37, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       41, 42, 43, 44, 45, 36, 36, 36,
+       36, 36, 36, 50, 51, 52, 36, 53,
+       54, 55, 36, 36, 36, 36, 42, 36,
+       37, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 42,
+       43, 44, 45, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 53, 54, 55,
+       36, 37, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 43, 44, 45, 36, 37, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 44, 45,
+       36, 37, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 45, 36, 37, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 43, 44, 45,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 53, 54, 55, 36, 37, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 43, 44,
+       45, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 54, 55, 36, 37,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 43,
+       44, 45, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 55, 36,
+       37, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 42,
+       43, 44, 45, 36, 36, 36, 36, 36,
+       36, 50, 51, 52, 36, 53, 54, 55,
+       36, 36, 36, 36, 42, 36, 37, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 42, 43, 44,
+       45, 36, 36, 36, 36, 36, 36, 36,
+       51, 52, 36, 53, 54, 55, 36, 36,
+       36, 36, 42, 36, 37, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 42, 43, 44, 45, 36,
+       36, 36, 36, 36, 36, 36, 36, 52,
+       36, 53, 54, 55, 36, 36, 36, 36,
+       42, 36, 37, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       41, 42, 43, 44, 45, 36, 47, 41,
+       36, 36, 36, 50, 51, 52, 36, 53,
+       54, 55, 36, 36, 36, 36, 42, 36,
+       37, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 41, 42,
+       43, 44, 45, 36, 60, 41, 36, 36,
+       36, 50, 51, 52, 36, 53, 54, 55,
+       36, 36, 36, 36, 42, 36, 37, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 36, 36, 41, 42, 43, 44,
+       45, 36, 36, 41, 36, 36, 36, 50,
+       51, 52, 36, 53, 54, 55, 36, 36,
+       36, 36, 42, 36, 37, 36, 36, 36,
+       36, 36, 36, 36, 36, 36, 36, 36,
+       36, 36, 41, 42, 43, 44, 45, 46,
+       47, 41, 36, 36, 36, 50, 51, 52,
+       36, 53, 54, 55, 36, 36, 36, 36,
+       42, 36, 37, 36, 36, 38, 1, 36,
+       36, 39, 36, 36, 36, 36, 36, 36,
+       41, 42, 43, 44, 45, 46, 47, 41,
+       48, 36, 49, 50, 51, 52, 36, 53,
+       54, 55, 36, 36, 36, 36, 56, 36,
+       38, 58, 58, 58, 58, 58, 58, 37,
+       58, 58, 58, 58, 58, 58, 59, 58,
+       58, 58, 58, 58, 58, 58, 42, 43,
+       44, 45, 58, 58, 58, 58, 58, 58,
+       58, 58, 58, 58, 53, 54, 55, 58,
+       37, 36, 36, 38, 1, 36, 36, 39,
+       36, 36, 36, 36, 36, 36, 41, 42,
+       43, 44, 45, 46, 47, 41, 48, 40,
+       49, 50, 51, 52, 36, 53, 54, 55,
+       36, 36, 36, 36, 56, 36, 62, 61,
+       61, 61, 61, 61, 61, 61, 63, 61,
+       10, 64, 62, 61, 11, 65, 65, 3,
+       6, 65, 65, 66, 65, 65, 65, 65,
+       65, 67, 16, 17, 18, 19, 20, 21,
+       22, 16, 23, 25, 25, 26, 27, 28,
+       65, 29, 30, 31, 65, 65, 65, 65,
+       33, 65, 11, 65, 65, 3, 6, 65,
+       65, 66, 65, 65, 65, 65, 65, 65,
        16, 17, 18, 19, 20, 21, 22, 16, 
-       23, 25, 25, 26, 27, 28, 63, 29, 
-       30, 31, 63, 11, 63, 63, 3, 6, 
-       63, 63, 64, 63, 63, 63, 63, 63, 
-       63, 16, 17, 18, 19, 20, 21, 22, 
-       16, 23, 25, 25, 26, 27, 28, 63, 
-       29, 30, 31, 63, 11, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 16, 17, 18, 19, 20, 63, 
-       63, 63, 63, 63, 63, 26, 27, 28, 
-       63, 29, 30, 31, 63, 11, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 17, 18, 19, 20, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 29, 30, 31, 63, 11, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 18, 19, 
-       20, 63, 11, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 19, 20, 63, 11, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       20, 63, 11, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 18, 19, 20, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 29, 
-       30, 31, 63, 11, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 18, 19, 20, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 30, 31, 63, 11, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 18, 19, 20, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 31, 63, 11, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 17, 18, 19, 20, 
-       63, 63, 63, 63, 63, 63, 26, 27, 
-       28, 63, 29, 30, 31, 63, 11, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 17, 18, 19, 
-       20, 63, 63, 63, 63, 63, 63, 63, 
-       27, 28, 63, 29, 30, 31, 63, 11, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 17, 18, 
-       19, 20, 63, 63, 63, 63, 63, 63, 
-       63, 63, 28, 63, 29, 30, 31, 63, 
-       11, 63, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 16, 17, 
-       18, 19, 20, 63, 22, 16, 63, 63, 
-       63, 26, 27, 28, 63, 29, 30, 31, 
-       63, 11, 63, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 16, 
-       17, 18, 19, 20, 63, 66, 16, 63, 
-       63, 63, 26, 27, 28, 63, 29, 30, 
-       31, 63, 11, 63, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       16, 17, 18, 19, 20, 63, 63, 16, 
-       63, 63, 63, 26, 27, 28, 63, 29, 
-       30, 31, 63, 11, 63, 63, 63, 63, 
-       63, 63, 63, 63, 63, 63, 63, 63, 
-       63, 16, 17, 18, 19, 20, 21, 22, 
-       16, 63, 63, 63, 26, 27, 28, 63, 
-       29, 30, 31, 63, 11, 63, 63, 3, 
-       6, 63, 63, 64, 63, 63, 63, 63, 
-       63, 63, 16, 17, 18, 19, 20, 21, 
-       22, 16, 23, 63, 25, 26, 27, 28, 
-       63, 29, 30, 31, 63, 3, 67, 67, 
-       67, 67, 67, 67, 67, 67, 67, 67, 
-       67, 67, 67, 4, 67, 6, 67, 8, 
-       63, 63, 63, 8, 63, 63, 11, 63, 
-       63, 3, 6, 63, 63, 64, 63, 63, 
-       63, 63, 63, 63, 16, 17, 18, 19, 
-       20, 21, 22, 16, 23, 24, 25, 26, 
-       27, 28, 63, 29, 30, 31, 63, 11, 
-       63, 63, 3, 6, 63, 63, 64, 63, 
-       63, 63, 63, 63, 63, 16, 17, 18, 
+       23, 25, 25, 26, 27, 28, 65, 29,
+       30, 31, 65, 65, 65, 65, 33, 65,
+       11, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 16, 17,
+       18, 19, 20, 65, 65, 65, 65, 65,
+       65, 26, 27, 28, 65, 29, 30, 31,
+       65, 65, 65, 65, 17, 65, 11, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 17, 18, 19,
+       20, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 29, 30, 31, 65, 11,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 18,
+       19, 20, 65, 11, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 19, 20, 65, 11,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 20, 65, 11, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 18, 19, 20, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       29, 30, 31, 65, 11, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 18, 19, 20, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 30, 31, 65, 11, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 18, 19, 20,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 31, 65, 11, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 17, 18, 19,
+       20, 65, 65, 65, 65, 65, 65, 26,
+       27, 28, 65, 29, 30, 31, 65, 65,
+       65, 65, 17, 65, 11, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 17, 18, 19, 20, 65,
+       65, 65, 65, 65, 65, 65, 27, 28,
+       65, 29, 30, 31, 65, 65, 65, 65,
+       17, 65, 11, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 17, 18, 19, 20, 65, 65, 65,
+       65, 65, 65, 65, 65, 28, 65, 29,
+       30, 31, 65, 65, 65, 65, 17, 65,
+       11, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 16, 17,
+       18, 19, 20, 65, 22, 16, 65, 65,
+       65, 26, 27, 28, 65, 29, 30, 31,
+       65, 65, 65, 65, 17, 65, 11, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 16, 17, 18, 19,
+       20, 65, 68, 16, 65, 65, 65, 26,
+       27, 28, 65, 29, 30, 31, 65, 65,
+       65, 65, 17, 65, 11, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 16, 17, 18, 19, 20, 65,
+       65, 16, 65, 65, 65, 26, 27, 28,
+       65, 29, 30, 31, 65, 65, 65, 65,
+       17, 65, 11, 65, 65, 65, 65, 65,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       16, 17, 18, 19, 20, 21, 22, 16,
+       65, 65, 65, 26, 27, 28, 65, 29,
+       30, 31, 65, 65, 65, 65, 17, 65,
+       11, 65, 65, 3, 6, 65, 65, 66,
+       65, 65, 65, 65, 65, 65, 16, 17,
+       18, 19, 20, 21, 22, 16, 23, 65,
+       25, 26, 27, 28, 65, 29, 30, 31,
+       65, 65, 65, 65, 33, 65, 3, 65,
+       65, 65, 65, 65, 65, 11, 65, 65,
+       65, 65, 65, 65, 4, 65, 65, 65,
+       65, 65, 65, 65, 17, 18, 19, 20,
+       65, 65, 65, 65, 65, 65, 65, 65,
+       65, 65, 29, 30, 31, 65, 3, 69,
+       69, 69, 69, 69, 69, 69, 69, 69,
+       69, 69, 69, 69, 4, 69, 6, 69,
+       69, 69, 69, 69, 69, 69, 69, 69,
+       69, 69, 69, 69, 69, 69, 69, 69,
+       69, 69, 69, 69, 69, 69, 69, 69,
+       69, 69, 69, 69, 69, 69, 6, 69,
+       8, 65, 65, 65, 8, 65, 65, 11,
+       65, 65, 3, 6, 65, 65, 66, 65,
+       65, 65, 65, 65, 65, 16, 17, 18,
        19, 20, 21, 22, 16, 23, 24, 25, 
-       26, 27, 28, 63, 29, 30, 31, 63, 
-       69, 68, 68, 68, 68, 68, 68, 68, 
-       68, 68, 68, 68, 68, 68, 68, 68, 
-       68, 68, 68, 68, 69, 70, 68, 69, 
-       70, 68, 70, 68, 8, 67, 67, 67, 
-       8, 67, 0
+       26, 27, 28, 65, 29, 30, 31, 65,
+       65, 65, 65, 33, 65, 11, 65, 65,
+       3, 6, 65, 65, 66, 65, 65, 65,
+       65, 65, 65, 16, 17, 18, 19, 20,
+       21, 22, 16, 23, 24, 25, 26, 27,
+       28, 65, 29, 30, 31, 65, 65, 65,
+       65, 33, 65, 71, 70, 70, 70, 70,
+       70, 70, 70, 70, 70, 70, 70, 70,
+       70, 70, 70, 70, 70, 70, 70, 71,
+       72, 70, 71, 72, 70, 72, 70, 8,
+       69, 69, 69, 8, 69, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-       4, 8, 4, 31, 2, 4, 1, 5, 
-       6, 4, 28, 4, 49, 50, 51, 53, 
-       33, 34, 35, 36, 37, 44, 45, 47, 
-       52, 48, 41, 42, 43, 38, 39, 40, 
-       56, 4, 4, 4, 4, 7, 0, 27, 
-       11, 12, 13, 14, 15, 22, 23, 25, 
-       26, 19, 20, 21, 16, 17, 18, 10, 
-       4, 9, 24, 4, 29, 30, 4, 4, 
-       3, 32, 46, 4, 4, 54, 55
+       4, 8, 4, 32, 2, 4, 1, 5,
+       6, 4, 29, 4, 51, 52, 53, 55,
+       34, 35, 36, 37, 38, 45, 46, 48,
+       54, 49, 42, 43, 44, 39, 40, 41,
+       58, 50, 4, 4, 4, 4, 7, 0,
+       28, 11, 12, 13, 14, 15, 22, 23,
+       25, 26, 19, 20, 21, 16, 17, 18,
+       27, 10, 4, 9, 24, 4, 30, 31,
+       4, 4, 3, 33, 47, 4, 4, 56,
+       57
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
@@ -264,11 +303,12 @@ static const char _use_syllable_machine_trans_actions[] = {
        7, 8, 0, 9, 10, 10, 3, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        3, 3, 0, 0, 0, 0, 0, 0, 
-       0, 11, 12, 13, 14, 7, 0, 7, 
-       0, 0, 0, 0, 0, 0, 0, 0, 
-       7, 0, 0, 0, 0, 0, 0, 7, 
-       15, 0, 0, 16, 0, 0, 17, 18, 
-       0, 3, 0, 19, 20, 0, 0
+       0, 3, 11, 12, 13, 14, 7, 0,
+       7, 0, 0, 0, 0, 0, 0, 0,
+       0, 7, 0, 0, 0, 0, 0, 0,
+       0, 7, 15, 0, 0, 16, 0, 0,
+       17, 18, 0, 3, 0, 19, 20, 0,
+       0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
@@ -279,7 +319,7 @@ static const char _use_syllable_machine_to_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0
+       0, 0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
@@ -290,18 +330,18 @@ static const char _use_syllable_machine_from_state_actions[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 
-       0
+       0, 0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-       1, 3, 3, 6, 0, 34, 36, 36, 
-       57, 57, 36, 36, 36, 36, 36, 36, 
-       36, 36, 36, 36, 36, 36, 36, 36, 
-       36, 36, 36, 36, 60, 63, 60, 64, 
-       64, 64, 64, 64, 64, 64, 64, 64, 
-       64, 64, 64, 64, 64, 64, 64, 64, 
-       64, 68, 68, 64, 64, 69, 69, 69, 
-       68
+       1, 3, 3, 6, 0, 35, 37, 37,
+       59, 59, 37, 37, 37, 37, 37, 37,
+       37, 37, 37, 37, 37, 37, 37, 37,
+       37, 37, 37, 59, 37, 62, 65, 62,
+       66, 66, 66, 66, 66, 66, 66, 66,
+       66, 66, 66, 66, 66, 66, 66, 66,
+       66, 66, 66, 70, 70, 66, 66, 71,
+       71, 71, 70
 };
 
 static const int use_syllable_machine_start = 4;
@@ -315,15 +355,14 @@ static const int use_syllable_machine_en_main = 4;
 
 
 
-#line 141 "hb-ot-shape-complex-use-machine.rl"
+#line 143 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -331,11 +370,11 @@ static const int use_syllable_machine_en_main = 4;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 339 "hb-ot-shape-complex-use-machine.hh"
+#line 378 "hb-ot-shape-complex-use-machine.hh"
        {
        cs = use_syllable_machine_start;
        ts = 0;
@@ -343,16 +382,15 @@ find_syllables (hb_buffer_t *buffer)
        act = 0;
        }
 
-#line 162 "hb-ot-shape-complex-use-machine.rl"
+#line 163 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 356 "hb-ot-shape-complex-use-machine.hh"
+#line 394 "hb-ot-shape-complex-use-machine.hh"
        {
        int _slen;
        int _trans;
@@ -366,7 +404,7 @@ _resume:
 #line 1 "NONE"
        {ts = p;}
        break;
-#line 370 "hb-ot-shape-complex-use-machine.hh"
+#line 408 "hb-ot-shape-complex-use-machine.hh"
        }
 
        _keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -389,59 +427,59 @@ _eof_trans:
        {te = p+1;}
        break;
        case 12:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
        {te = p+1;{ found_syllable (independent_cluster); }}
        break;
        case 14:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
        {te = p+1;{ found_syllable (standard_cluster); }}
        break;
        case 9:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
        {te = p+1;{ found_syllable (broken_cluster); }}
        break;
        case 8:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
        {te = p+1;{ found_syllable (non_cluster); }}
        break;
        case 11:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (independent_cluster); }}
        break;
        case 15:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
+#line 133 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (virama_terminated_cluster); }}
        break;
        case 13:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (standard_cluster); }}
        break;
        case 17:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
        break;
        case 16:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (numeral_cluster); }}
        break;
        case 20:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 137 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (symbol_cluster); }}
        break;
        case 18:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (broken_cluster); }}
        break;
        case 19:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
        {te = p;p--;{ found_syllable (non_cluster); }}
        break;
        case 1:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
        {{p = ((te))-1;}{ found_syllable (standard_cluster); }}
        break;
        case 4:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
        break;
        case 2:
@@ -459,16 +497,16 @@ _eof_trans:
        case 3:
 #line 1 "NONE"
        {te = p+1;}
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
        {act = 7;}
        break;
        case 10:
 #line 1 "NONE"
        {te = p+1;}
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
        {act = 8;}
        break;
-#line 472 "hb-ot-shape-complex-use-machine.hh"
+#line 510 "hb-ot-shape-complex-use-machine.hh"
        }
 
 _again:
@@ -477,7 +515,7 @@ _again:
 #line 1 "NONE"
        {ts = 0;}
        break;
-#line 481 "hb-ot-shape-complex-use-machine.hh"
+#line 519 "hb-ot-shape-complex-use-machine.hh"
        }
 
        if ( ++p != pe )
index 7ec8a7f..7702cd9 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 %%{
   machine use_syllable_machine;
@@ -88,22 +88,19 @@ SMAbv       = 41; # SYM_MOD_ABOVE
 SMBlw  = 42; # SYM_MOD_BELOW
 CS     = 43; # CONS_WITH_STACKER
 
+HVM    = 44; # HALANT_OR_VOWEL_MODIFIER
+
+h = H | HVM; # https://github.com/harfbuzz/harfbuzz/issues/1102
 
 # Override: Adhoc ZWJ placement. https://github.com/harfbuzz/harfbuzz/issues/542#issuecomment-353169729
-consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.H.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*;
+consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.h.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*;
 # Override: Allow two MBlw. https://github.com/harfbuzz/harfbuzz/issues/376
 medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
 dependent_vowels = VPre* VAbv* VBlw* VPst*;
-vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
+vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*;
 final_consonants = FAbv* FBlw* FPst* FM?;
 
-virama_terminated_cluster =
-       (R|CS)? (B | GB) VS?
-       consonant_modifiers
-       ZWJ?.H.ZWJ?
-;
-standard_cluster =
-       (R|CS)? (B | GB) VS?
+complex_syllable_tail =
        consonant_modifiers
        medial_consonants
        dependent_vowels
@@ -111,13 +108,18 @@ standard_cluster =
        final_consonants
 ;
 
+virama_terminated_cluster =
+       (R|CS)? (B | GB) VS?
+       consonant_modifiers
+       ZWJ?.h.ZWJ?
+;
+standard_cluster =
+       (R|CS)? (B | GB) VS?
+       complex_syllable_tail
+;
 broken_cluster =
        R?
-       consonant_modifiers
-       medial_consonants
-       dependent_vowels
-       vowel_modifiers
-       final_consonants
+       complex_syllable_tail
 ;
 
 number_joiner_terminated_cluster = N VS? (HN N VS?)* HN;
@@ -142,10 +144,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -153,7 +154,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -164,7 +165,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-use-private.hh b/src/hb-ot-shape-complex-use-private.hh
deleted file mode 100644 (file)
index b4bda8b..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  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.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-#define USE_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the Universal Shaping Engine spec:
- * https://docs.microsoft.com/en-us/typography/script-development/use
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum use_category_t {
-  USE_O                = 0,    /* OTHER */
-
-  USE_B                = 1,    /* BASE */
-  USE_IND      = 3,    /* BASE_IND */
-  USE_N                = 4,    /* BASE_NUM */
-  USE_GB       = 5,    /* BASE_OTHER */
-  USE_CGJ      = 6,    /* CGJ */
-//  USE_F              = 7,    /* CONS_FINAL */
-  USE_FM       = 8,    /* CONS_FINAL_MOD */
-//  USE_M              = 9,    /* CONS_MED */
-//  USE_CM     = 10,   /* CONS_MOD */
-  USE_SUB      = 11,   /* CONS_SUB */
-  USE_H                = 12,   /* HALANT */
-
-  USE_HN       = 13,   /* HALANT_NUM */
-  USE_ZWNJ     = 14,   /* Zero width non-joiner */
-  USE_ZWJ      = 15,   /* Zero width joiner */
-  USE_WJ       = 16,   /* Word joiner */
-  USE_Rsv      = 17,   /* Reserved characters */
-  USE_R                = 18,   /* REPHA */
-  USE_S                = 19,   /* SYM */
-//  USE_SM     = 20,   /* SYM_MOD */
-  USE_VS       = 21,   /* VARIATION_SELECTOR */
-//  USE_V      = 36,   /* VOWEL */
-//  USE_VM     = 40,   /* VOWEL_MOD */
-
-  USE_FAbv     = 24,   /* CONS_FINAL_ABOVE */
-  USE_FBlw     = 25,   /* CONS_FINAL_BELOW */
-  USE_FPst     = 26,   /* CONS_FINAL_POST */
-  USE_MAbv     = 27,   /* CONS_MED_ABOVE */
-  USE_MBlw     = 28,   /* CONS_MED_BELOW */
-  USE_MPst     = 29,   /* CONS_MED_POST */
-  USE_MPre     = 30,   /* CONS_MED_PRE */
-  USE_CMAbv    = 31,   /* CONS_MOD_ABOVE */
-  USE_CMBlw    = 32,   /* CONS_MOD_BELOW */
-  USE_VAbv     = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
-  USE_VBlw     = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
-  USE_VPst     = 35,   /* VOWEL_POST   UIPC = Right */
-  USE_VPre     = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
-  USE_VMAbv    = 37,   /* VOWEL_MOD_ABOVE */
-  USE_VMBlw    = 38,   /* VOWEL_MOD_BELOW */
-  USE_VMPst    = 39,   /* VOWEL_MOD_POST */
-  USE_VMPre    = 23,   /* VOWEL_MOD_PRE */
-  USE_SMAbv    = 41,   /* SYM_MOD_ABOVE */
-  USE_SMBlw    = 42,   /* SYM_MOD_BELOW */
-  USE_CS       = 43    /* CONS_WITH_STACKER */
-};
-
-HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u);
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
index 1431533..835b95b 100644 (file)
  * UnicodeData.txt does not have a header.
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
+#include "hb-ot-shape-complex-use.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define B      USE_B   /* BASE */
 #define CGJ    USE_CGJ /* CGJ */
 #define CS     USE_CS  /* CONS_WITH_STACKER */
@@ -24,6 +26,7 @@
 #define GB     USE_GB  /* BASE_OTHER */
 #define H      USE_H   /* HALANT */
 #define HN     USE_HN  /* HALANT_NUM */
+#define HVM    USE_HVM /* HALANT_OR_VOWEL_MODIFIER */
 #define IND    USE_IND /* BASE_IND */
 #define N      USE_N   /* BASE_NUM */
 #define O      USE_O   /* OTHER */
@@ -54,6 +57,7 @@
 #define VMBlw  USE_VMBlw
 #define VMPst  USE_VMPst
 #define VMAbv  USE_VMAbv
+#pragma GCC diagnostic pop
 
 static const USE_TABLE_ELEMENT_TYPE use_table[] = {
 
@@ -101,7 +105,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,   IND,     O,
+  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,     H,   IND,     O,
   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,    FM,     O,
@@ -134,7 +138,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0B10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0B30 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
-  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,     O,     O,  VPst,  VPst,     H,     O,     O,
   /* 0B50 */     O,     O,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 0B60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B70 */     O,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -145,7 +149,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0B90 */     B,     O,     B,     B,     B,     B,     O,     O,     O,     B,     B,     O,     B,     O,     B,     B,
   /* 0BA0 */     O,     O,     O,     B,     B,     O,     O,     O,     B,     B,     B,     O,     O,     O,     B,     B,
   /* 0BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,  VPst,  VPst,
-  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     O,     O,
+  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     O,     O,
   /* 0BD0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 0BE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0BF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -178,7 +182,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0D10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,     B,  VPst,  VPst,
-  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     R,     O,
+  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     R,     O,
   /* 0D50 */     O,     O,     O,     O,   IND,   IND,   IND,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,
   /* 0D60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,   IND,   IND,   IND,   IND,   IND,   IND,
@@ -190,11 +194,28 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DB0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     O,
   /* 0DC0 */     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     H,     O,     O,     O,     O,  VPst,
-  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPre,  VPre,  VPre,  VPre,  VPre,  VPst,
+  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPst,  VPre,  VPst,  VPst,  VPst,  VPst,
   /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
 
-#define use_offset_0x1000u 1360
+#define use_offset_0x0f18u 1360
+
+
+  /* Tibetan */
+                                                                      VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
+  /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
+  /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
+  /* 0F70 */     O,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw, VMAbv, VMPst,
+  /* 0F80 */  VBlw,  VAbv, VMAbv, VMAbv,  VBlw,   IND, VMAbv, VMAbv,     B,     B,     B,     B,     B,   SUB,   SUB,   SUB,
+  /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
+  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
+
+#define use_offset_0x1000u 1536
 
 
   /* Myanmar */
@@ -210,7 +231,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
   /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
 
-#define use_offset_0x1700u 1520
+#define use_offset_0x1700u 1696
 
 
   /* Tagalog */
@@ -238,12 +259,12 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
-  /* 17C0 */  VPre,  VPre,  VPre,  VPre,  VPre,  VPre, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
+  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPst,  VPst,
+  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
   /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,  VAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1900u 1760
+#define use_offset_0x1900u 1936
 
 
   /* Limbu */
@@ -287,7 +308,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1b00u 2176
+#define use_offset_0x1b00u 2352
 
 
   /* Balinese */
@@ -296,7 +317,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1B10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
-  /* 1B40 */  VPre,  VPre,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
+  /* 1B40 */  VPst,  VPst,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
   /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1B60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -319,11 +340,11 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
 
   /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPre,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
+  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
-#define use_offset_0x1cd0u 2512
+#define use_offset_0x1cd0u 2688
 
 
   /* Vedic Extensions */
@@ -332,20 +353,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
   /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1df8u 2560
+#define use_offset_0x1df8u 2736
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O,    FM,     O,     O,     O,     O,
 
-#define use_offset_0x2008u 2568
+#define use_offset_0x2008u 2744
 
 
   /* General Punctuation */
                                                                          O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
 
-#define use_offset_0x2060u 2584
+#define use_offset_0x2060u 2760
 
   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -354,20 +375,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
 
-#define use_offset_0x20f0u 2624
+#define use_offset_0x20f0u 2800
 
 
   /* Combining Diacritical Marks for Symbols */
 
   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x25c8u 2632
+#define use_offset_0x25c8u 2808
 
 
   /* Geometric Shapes */
                                                                          O,     O,     O,     O,    GB,     O,     O,     O,
 
-#define use_offset_0xa800u 2640
+#define use_offset_0xa800u 2816
 
 
   /* Syloti Nagri */
@@ -454,7 +475,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3400
+#define use_offset_0xabc0u 3576
 
 
   /* Meetei Mayek */
@@ -464,14 +485,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0xfe00u 3464
+#define use_offset_0xfe00u 3640
 
 
   /* Variation Selectors */
 
   /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
 
-#define use_offset_0x10a00u 3480
+#define use_offset_0x10a00u 3656
 
 
   /* Kharoshthi */
@@ -482,7 +503,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 10A30 */     B,     B,     B,     B,     B,     B,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11000u 3560
+#define use_offset_0x11000u 3736
 
 
   /* Brahmi */
@@ -491,7 +512,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
-  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,   HVM,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
   /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11070 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,    HN,
@@ -503,15 +524,15 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 3752
+#define use_offset_0x11100u 3928
 
 
   /* Chakma */
 
   /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VAbv,  VAbv,
-  /* 11130 */  VAbv,  VBlw,  VBlw,     H,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VBlw,  VAbv,  VAbv,
+  /* 11130 */  VBlw,  VAbv,  VAbv,     H, CMBlw,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11140 */     O,     O,     O,     O,     B,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Mahajani */
@@ -526,7 +547,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
-  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,     O,    FM, CMBlw,  VAbv,  VBlw,     O,     O,     O,
+  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB,  FBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
   /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Sinhala Archaic Numbers */
@@ -541,7 +562,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4072
+#define use_offset_0x11280u 4248
 
 
   /* Multani */
@@ -560,16 +581,16 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
 
   /* Grantha */
 
-  /* 11300 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
+  /* 11300 */ VMAbv, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O, CMBlw, CMBlw,     B,  VPst,  VPst,
-  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,   HVM,     O,     O,
   /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 4320
+#define use_offset_0x11400u 4496
 
 
   /* Newa */
@@ -588,11 +609,11 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPre,  VPre,  VPst,  VPre, VMAbv,
+  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPst,  VPst,  VPst,  VPst, VMAbv,
   /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 4544
+#define use_offset_0x11580u 4720
 
 
   /* Siddham */
@@ -600,7 +621,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11590 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 115A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
-  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,  VPre,  VPre, VMAbv, VMAbv, VMPst,     H,
+  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,  VPst,  VPst, VMAbv, VMAbv, VMPst,     H,
   /* 115C0 */ CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 115D0 */     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,  VBlw,  VBlw,     O,     O,
   /* 115E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -635,7 +656,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11800u 4992
+#define use_offset_0x11800u 5168
 
 
   /* Dogra */
@@ -645,7 +666,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,
   /* 11830 */  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11a00u 5056
+#define use_offset_0x11a00u 5232
 
 
   /* Zanabazar Square */
@@ -664,7 +685,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     B,     O,     O,
 
-#define use_offset_0x11c00u 5216
+#define use_offset_0x11c00u 5392
 
 
   /* Bhaiksuki */
@@ -673,7 +694,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
-  /* 11C40 */     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11C40 */     B,     O,     O,     O,    GB,    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11C50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
 
@@ -685,7 +706,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 5400
+#define use_offset_0x11d00u 5576
 
 
   /* Masaram Gondi */
@@ -705,7 +726,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11D90 */  VAbv,  VAbv,     O,  VPst,  VPst, VMAbv, VMPst,     H,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11ee0u 5576
+#define use_offset_0x11ee0u 5752
 
 
   /* Makasar */
@@ -713,7 +734,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11EE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11EF0 */     B,     B,    GB,  VAbv,  VBlw,  VPre,  VPst,     O,
 
-}; /* Table items: 5600; occupancy: 73% */
+}; /* Table items: 5776; occupancy: 74% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_category (hb_codepoint_t u)
@@ -725,6 +746,7 @@ hb_use_get_category (hb_codepoint_t u)
       if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x0F18u, 0x0FC7u)) return use_table[u - 0x0F18u + use_offset_0x0f18u];
       break;
 
     case 0x1u:
@@ -782,6 +804,7 @@ hb_use_get_category (hb_codepoint_t u)
 #undef GB
 #undef H
 #undef HN
+#undef HVM
 #undef IND
 #undef N
 #undef O
index 66b9571..2e3f202 100644 (file)
@@ -26,8 +26,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
+#include "hb-ot-shape-complex-use.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
 
 /* buffer var allocations */
 #define use_category() complex_var_u8_0()
@@ -79,14 +80,22 @@ other_features[] =
 {
   /*
    * Other features.
-   * These features are applied all at once, after reordering.
+   * These features are applied all at once, after reordering and
+   * clearing syllables.
    */
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('h','a','l','n'),
   HB_TAG('p','r','e','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   HB_TAG('a','b','v','m'),
   HB_TAG('b','l','w','m'),
@@ -112,6 +121,10 @@ static void
 reorder (const hb_ot_shape_plan_t *plan,
         hb_font_t *font,
         hb_buffer_t *buffer);
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                hb_font_t *font,
+                hb_buffer_t *buffer);
 
 static void
 collect_features_use (hb_ot_shape_planner_t *plan)
@@ -122,39 +135,42 @@ collect_features_use (hb_ot_shape_planner_t *plan)
   map->add_gsub_pause (setup_syllables);
 
   /* "Default glyph pre-processing group" */
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('n','u','k','t'));
-  map->add_global_bool_feature (HB_TAG('a','k','h','n'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('n','u','k','t'));
+  map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
 
   /* "Reordering group" */
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
+  map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_rphf);
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_pref);
 
   /* "Orthographic unit shaping group" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
 
   map->add_gsub_pause (reorder);
+  map->add_gsub_pause (clear_syllables);
 
   /* "Topographical features" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
-    map->add_feature (arabic_features[i], 1, F_NONE);
+    map->add_feature (arabic_features[i]);
   map->add_gsub_pause (nullptr);
 
-  /* "Standard typographic presentation" and "Positional feature application" */
+  /* "Standard typographic presentation" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  /* "Positional feature application" */
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 struct use_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t rphf_mask;
 
   arabic_shape_plan_t *arabic_plan;
@@ -361,7 +377,7 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
 }
 
 static void
-clear_substitution_flags (const hb_ot_shape_plan_t *plan,
+clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
                          hb_font_t *font HB_UNUSED,
                          hb_buffer_t *buffer)
 {
@@ -373,7 +389,7 @@ clear_substitution_flags (const hb_ot_shape_plan_t *plan,
 
 static void
 record_rphf (const hb_ot_shape_plan_t *plan,
-            hb_font_t *font,
+            hb_font_t *font HB_UNUSED,
             hb_buffer_t *buffer)
 {
   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
@@ -395,8 +411,8 @@ record_rphf (const hb_ot_shape_plan_t *plan,
 }
 
 static void
-record_pref (const hb_ot_shape_plan_t *plan,
-            hb_font_t *font,
+record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
+            hb_font_t *font HB_UNUSED,
             hb_buffer_t *buffer)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -416,7 +432,8 @@ record_pref (const hb_ot_shape_plan_t *plan,
 static inline bool
 is_halant (const hb_glyph_info_t &info)
 {
-  return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
+  return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
+        !_hb_glyph_info_ligated (&info);
 }
 
 static void
@@ -433,19 +450,38 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
 
   hb_glyph_info_t *info = buffer->info;
 
-#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
+#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
+                          FLAG64 (USE_FAbv) | \
+                          FLAG64 (USE_FBlw) | \
+                          FLAG64 (USE_FPst) | \
+                          FLAG64 (USE_MAbv) | \
+                          FLAG64 (USE_MBlw) | \
+                          FLAG64 (USE_MPst) | \
+                          FLAG64 (USE_MPre) | \
+                          FLAG64 (USE_VAbv) | \
+                          FLAG64 (USE_VBlw) | \
+                          FLAG64 (USE_VPst) | \
+                          FLAG64 (USE_VPre) | \
+                          FLAG64 (USE_VMAbv) | \
+                          FLAG64 (USE_VMBlw) | \
+                          FLAG64 (USE_VMPst) | \
+                          FLAG64 (USE_VMPre))
 
   /* Move things forward. */
   if (info[start].use_category() == USE_R && end - start > 1)
   {
-    /* Got a repha.  Reorder it to after first base, before first halant. */
+    /* Got a repha.  Reorder it towards the end, but before the first post-base
+     * glyph. */
     for (unsigned int i = start + 1; i < end; i++)
-      if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
+    {
+      bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
+                               is_halant (info[i]);
+      if (is_post_base_glyph || i == end - 1)
       {
-       /* If we hit a halant, move before it; otherwise it's a base: move to it's
-        * place, and shift things in between backward. */
+       /* If we hit a post-base glyph, move before it; otherwise move to the
+        * end. Shift things in between backward. */
 
-       if (is_halant (info[i]))
+       if (is_post_base_glyph)
          i--;
 
        buffer->merge_clusters (start, i + 1);
@@ -455,21 +491,19 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
 
        break;
       }
+    }
   }
 
   /* Move things back. */
-  unsigned int j = end;
+  unsigned int j = start;
   for (unsigned int i = start; i < end; i++)
   {
     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
-    if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
+    if (is_halant (info[i]))
     {
-      /* If we hit a halant, move after it; otherwise it's a base: move to it's
-       * place, and shift things in between backward. */
-      if (is_halant (info[i]))
-       j = i + 1;
-      else
-       j = i;
+      /* If we hit a halant, move after it; otherwise move to the beginning, and
+       * shift things in between forward. */
+      j = i + 1;
     }
     else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
             /* Only move the first component of a MultipleSubst. */
@@ -536,7 +570,6 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -547,36 +580,30 @@ reorder (const hb_ot_shape_plan_t *plan,
 {
   insert_dotted_circles (plan, font, buffer);
 
-  hb_glyph_info_t *info = buffer->info;
-
   foreach_syllable (buffer, start, end)
     reorder_syllable (buffer, start, end);
 
-  /* Zero syllables now... */
+  HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
+}
+
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                hb_font_t *font HB_UNUSED,
+                hb_buffer_t *buffer)
+{
+  hb_glyph_info_t *info = buffer->info;
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     info[i].syllable() = 0;
-
-  HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
 }
 
-static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
-                hb_codepoint_t  ab,
-                hb_codepoint_t *a,
-                hb_codepoint_t *b)
-{
-  switch (ab)
-  {
-    /* Chakma:
-     * Special case where the Unicode decomp gives matras in the wrong order
-     * for cluster validation.
-     */
-    case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
-    case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
-  }
 
-  return (bool) c->unicode->decompose (ab, a, b);
+static void
+preprocess_text_use (const hb_ot_shape_plan_t *plan,
+                    hb_buffer_t              *buffer,
+                    hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
 }
 
 static bool
@@ -599,13 +626,13 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
   nullptr, /* override_features */
   data_create_use,
   data_destroy_use,
-  nullptr, /* preprocess_text */
+  preprocess_text_use,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_use,
+  nullptr, /* decompose */
   compose_use,
   setup_masks_use,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
diff --git a/src/hb-ot-shape-complex-use.hh b/src/hb-ot-shape-complex-use.hh
new file mode 100644 (file)
index 0000000..ab56e1b
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  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.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_USE_HH
+#define HB_OT_SHAPE_COMPLEX_USE_HH
+
+#include "hb.hh"
+
+
+#include "hb-ot-shape-complex.hh"
+
+
+#define USE_TABLE_ELEMENT_TYPE uint8_t
+
+/* Cateories used in the Universal Shaping Engine spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/use
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum use_category_t {
+  USE_O                = 0,    /* OTHER */
+
+  USE_B                = 1,    /* BASE */
+  USE_IND      = 3,    /* BASE_IND */
+  USE_N                = 4,    /* BASE_NUM */
+  USE_GB       = 5,    /* BASE_OTHER */
+  USE_CGJ      = 6,    /* CGJ */
+//  USE_F              = 7,    /* CONS_FINAL */
+  USE_FM       = 8,    /* CONS_FINAL_MOD */
+//  USE_M              = 9,    /* CONS_MED */
+//  USE_CM     = 10,   /* CONS_MOD */
+  USE_SUB      = 11,   /* CONS_SUB */
+  USE_H                = 12,   /* HALANT */
+
+  USE_HN       = 13,   /* HALANT_NUM */
+  USE_ZWNJ     = 14,   /* Zero width non-joiner */
+  USE_ZWJ      = 15,   /* Zero width joiner */
+  USE_WJ       = 16,   /* Word joiner */
+  USE_Rsv      = 17,   /* Reserved characters */
+  USE_R                = 18,   /* REPHA */
+  USE_S                = 19,   /* SYM */
+//  USE_SM     = 20,   /* SYM_MOD */
+  USE_VS       = 21,   /* VARIATION_SELECTOR */
+//  USE_V      = 36,   /* VOWEL */
+//  USE_VM     = 40,   /* VOWEL_MOD */
+
+  USE_FAbv     = 24,   /* CONS_FINAL_ABOVE */
+  USE_FBlw     = 25,   /* CONS_FINAL_BELOW */
+  USE_FPst     = 26,   /* CONS_FINAL_POST */
+  USE_MAbv     = 27,   /* CONS_MED_ABOVE */
+  USE_MBlw     = 28,   /* CONS_MED_BELOW */
+  USE_MPst     = 29,   /* CONS_MED_POST */
+  USE_MPre     = 30,   /* CONS_MED_PRE */
+  USE_CMAbv    = 31,   /* CONS_MOD_ABOVE */
+  USE_CMBlw    = 32,   /* CONS_MOD_BELOW */
+  USE_VAbv     = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
+  USE_VBlw     = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
+  USE_VPst     = 35,   /* VOWEL_POST   UIPC = Right */
+  USE_VPre     = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
+  USE_VMAbv    = 37,   /* VOWEL_MOD_ABOVE */
+  USE_VMBlw    = 38,   /* VOWEL_MOD_BELOW */
+  USE_VMPst    = 39,   /* VOWEL_MOD_POST */
+  USE_VMPre    = 23,   /* VOWEL_MOD_PRE */
+  USE_SMAbv    = 41,   /* SYM_MOD_ABOVE */
+  USE_SMBlw    = 42,   /* SYM_MOD_BELOW */
+  USE_CS       = 43,   /* CONS_WITH_STACKER */
+
+  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
+  USE_HVM      = 44,   /* HALANT_OR_VOWEL_MODIFIER */
+};
+
+HB_INTERNAL USE_TABLE_ELEMENT_TYPE
+hb_use_get_category (hb_codepoint_t u);
+
+#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */
diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc
new file mode 100644 (file)
index 0000000..0e53258
--- /dev/null
@@ -0,0 +1,437 @@
+/* == Start of generated functions == */
+/*
+ * The following functions are generated by running:
+ *
+ *   ./gen-vowel-constraints.py use Scripts.txt
+ *
+ * on files with these headers:
+ *
+ * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use
+ * # On October 23, 2018; with documentd dated 02/07/2018.
+ *
+ * # Scripts-11.0.0.txt
+ * # Date: 2018-02-21, 05:34:31 GMT
+ */
+
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+
+static void
+_output_dotted_circle (hb_buffer_t *buffer)
+{
+  hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);
+  _hb_glyph_info_reset_continuation (&dottedcircle);
+}
+
+static void
+_output_with_dotted_circle (hb_buffer_t *buffer)
+{
+  _output_dotted_circle (buffer);
+  buffer->next_glyph ();
+}
+
+void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                      hb_buffer_t              *buffer,
+                                      hb_font_t                *font HB_UNUSED)
+{
+  /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
+   * vowel-sequences that look like another vowel.  Data for each script
+   * collected from the USE script development spec.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1019
+   */
+  bool processed = false;
+  buffer->clear_output ();
+  unsigned int count = buffer->len;
+  switch ((unsigned) buffer->props.script)
+  {
+    case HB_SCRIPT_DEVANAGARI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0905u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u:
+             case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu:
+             case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0906u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u:
+             case 0x0948u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0909u:
+           matched = 0x0941u == buffer->cur (1).codepoint;
+           break;
+         case 0x090Fu:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0945u: case 0x0946u: case 0x0947u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0930u:
+           if (0x094Du == buffer->cur (1).codepoint &&
+               buffer->idx + 2 < count &&
+               0x0907u == buffer->cur (2).codepoint)
+           {
+             buffer->next_glyph ();
+             buffer->next_glyph ();
+             _output_dotted_circle (buffer);
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BENGALI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0985u:
+           matched = 0x09BEu == buffer->cur (1).codepoint;
+           break;
+         case 0x098Bu:
+           matched = 0x09C3u == buffer->cur (1).codepoint;
+           break;
+         case 0x098Cu:
+           matched = 0x09E2u == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GURMUKHI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0A05u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0A72u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0A3Fu: case 0x0A40u: case 0x0A47u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0A73u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0A41u: case 0x0A42u: case 0x0A4Bu:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GUJARATI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0A85u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u:
+             case 0x0AC9u: case 0x0ACBu: case 0x0ACCu:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0AC5u:
+           matched = 0x0ABEu == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_ORIYA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0B05u:
+           matched = 0x0B3Eu == buffer->cur (1).codepoint;
+           break;
+         case 0x0B0Fu: case 0x0B13u:
+           matched = 0x0B57u == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TELUGU:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0C12u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0C4Cu: case 0x0C55u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0C3Fu: case 0x0C46u: case 0x0C4Au:
+           matched = 0x0C55u == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KANNADA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0C89u: case 0x0C8Bu:
+           matched = 0x0CBEu == buffer->cur (1).codepoint;
+           break;
+         case 0x0C92u:
+           matched = 0x0CCCu == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MALAYALAM:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0D07u: case 0x0D09u:
+           matched = 0x0D57u == buffer->cur (1).codepoint;
+           break;
+         case 0x0D0Eu:
+           matched = 0x0D46u == buffer->cur (1).codepoint;
+           break;
+         case 0x0D12u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0D3Eu: case 0x0D57u:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_SINHALA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x0D85u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0DCFu: case 0x0DD0u: case 0x0DD1u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u:
+           matched = 0x0DDFu == buffer->cur (1).codepoint;
+           break;
+         case 0x0D8Du:
+           matched = 0x0DD8u == buffer->cur (1).codepoint;
+           break;
+         case 0x0D91u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu:
+             case 0x0DDDu:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BRAHMI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x11005u:
+           matched = 0x11038u == buffer->cur (1).codepoint;
+           break;
+         case 0x1100Bu:
+           matched = 0x1103Eu == buffer->cur (1).codepoint;
+           break;
+         case 0x1100Fu:
+           matched = 0x11042u == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KHUDAWADI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x112B0u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u:
+             case 0x112E8u:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TIRHUTA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x11481u:
+           matched = 0x114B0u == buffer->cur (1).codepoint;
+           break;
+         case 0x1148Bu: case 0x1148Du:
+           matched = 0x114BAu == buffer->cur (1).codepoint;
+           break;
+         case 0x114AAu:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x114B5u: case 0x114B6u:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MODI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x11600u: case 0x11601u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x11639u: case 0x1163Au:
+               matched = true;
+               break;
+           }
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TAKRI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+       bool matched = false;
+       switch (buffer->cur ().codepoint)
+       {
+         case 0x11680u:
+           switch (buffer->cur (1).codepoint)
+           {
+             case 0x116ADu: case 0x116B4u: case 0x116B5u:
+               matched = true;
+               break;
+           }
+           break;
+         case 0x11686u:
+           matched = 0x116B2u == buffer->cur (1).codepoint;
+           break;
+       }
+       buffer->next_glyph ();
+       if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    default:
+      break;
+  }
+  if (processed)
+  {
+    if (buffer->idx < count)
+      buffer->next_glyph ();
+    buffer->swap_buffers ();
+  }
+}
+
+/* == End of generated functions == */
diff --git a/src/hb-ot-shape-complex-vowel-constraints.hh b/src/hb-ot-shape-complex-vowel-constraints.hh
new file mode 100644 (file)
index 0000000..d9082d4
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+HB_INTERNAL void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
+                                      hb_buffer_t              *buffer,
+                                      hb_font_t                *font);
+
+#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
diff --git a/src/hb-ot-shape-complex.hh b/src/hb-ot-shape-complex.hh
new file mode 100644 (file)
index 0000000..a2499de
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2010,2011,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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_HH
+#define HB_OT_SHAPE_COMPLEX_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-normalize.hh"
+
+
+/* buffer var allocations, used by complex shapers */
+#define complex_var_u8_0()     var2.u8[2]
+#define complex_var_u8_1()     var2.u8[3]
+
+
+#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+
+enum hb_ot_shape_zero_width_marks_type_t {
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
+};
+
+
+/* Master OT shaper list */
+#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
+  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
+  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
+  /* ^--- Add new shapers here */
+
+
+struct hb_ot_complex_shaper_t
+{
+  /* collect_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to add their features and callbacks.
+   * May be NULL.
+   */
+  void (*collect_features) (hb_ot_shape_planner_t *plan);
+
+  /* override_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to override features and add callbacks after
+   * common features are added.
+   * May be NULL.
+   */
+  void (*override_features) (hb_ot_shape_planner_t *plan);
+
+
+  /* data_create()
+   * Called at the end of shape_plan().
+   * Whatever shapers return will be accessible through plan->data later.
+   * If nullptr is returned, means a plan failure.
+   */
+  void *(*data_create) (const hb_ot_shape_plan_t *plan);
+
+  /* data_destroy()
+   * Called when the shape_plan is being destroyed.
+   * plan->data is passed here for destruction.
+   * If nullptr is returned, means a plan failure.
+   * May be NULL.
+   */
+  void (*data_destroy) (void *data);
+
+
+  /* preprocess_text()
+   * Called during shape().
+   * Shapers can use to modify text before shaping starts.
+   * May be NULL.
+   */
+  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
+                          hb_buffer_t              *buffer,
+                          hb_font_t                *font);
+
+  /* postprocess_glyphs()
+   * Called during shape().
+   * Shapers can use to modify glyphs after shaping ends.
+   * May be NULL.
+   */
+  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
+                             hb_buffer_t              *buffer,
+                             hb_font_t                *font);
+
+
+  hb_ot_shape_normalization_mode_t normalization_preference;
+
+  /* decompose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                    hb_codepoint_t  ab,
+                    hb_codepoint_t *a,
+                    hb_codepoint_t *b);
+
+  /* compose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                  hb_codepoint_t  a,
+                  hb_codepoint_t  b,
+                  hb_codepoint_t *ab);
+
+  /* setup_masks()
+   * Called during shape().
+   * Shapers should use map to get feature masks and set on buffer.
+   * Shapers may NOT modify characters.
+   * May be NULL.
+   */
+  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
+                      hb_buffer_t              *buffer,
+                      hb_font_t                *font);
+
+  /* gpos_tag()
+   * If not HB_TAG_NONE, then must match found GPOS script tag for
+   * GPOS to be applied.  Otherwise, fallback positioning will be used.
+   */
+  hb_tag_t gpos_tag;
+
+  /* reorder_marks()
+   * Called during shape().
+   * Shapers can use to modify ordering of combining marks.
+   * May be NULL.
+   */
+  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
+                        hb_buffer_t              *buffer,
+                        unsigned int              start,
+                        unsigned int              end);
+
+  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
+
+  bool fallback_position;
+};
+
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
+HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+
+
+static inline const hb_ot_complex_shaper_t *
+hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
+{
+  switch ((hb_tag_t) planner->props.script)
+  {
+    default:
+      return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_ARABIC:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_MONGOLIAN:
+    case HB_SCRIPT_SYRIAC:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_NKO:
+    case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_PSALTER_PAHLAVI:
+
+    /* Unicode-9.0 additions */
+    case HB_SCRIPT_ADLAM:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_SOGDIAN:
+
+      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
+       * This is because we do fallback shaping for Arabic script (and not others).
+       * But note that Arabic shaping is applicable only to horizontal layout; for
+       * vertical text, just use the generic shaper instead. */
+      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+          planner->props.script == HB_SCRIPT_ARABIC) &&
+         HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
+       return &_hb_ot_complex_shaper_arabic;
+      else
+       return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_THAI:
+    case HB_SCRIPT_LAO:
+
+      return &_hb_ot_complex_shaper_thai;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HANGUL:
+
+      return &_hb_ot_complex_shaper_hangul;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HEBREW:
+
+      return &_hb_ot_complex_shaper_hebrew;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_BENGALI:
+    case HB_SCRIPT_DEVANAGARI:
+    case HB_SCRIPT_GUJARATI:
+    case HB_SCRIPT_GURMUKHI:
+    case HB_SCRIPT_KANNADA:
+    case HB_SCRIPT_MALAYALAM:
+    case HB_SCRIPT_ORIYA:
+    case HB_SCRIPT_TAMIL:
+    case HB_SCRIPT_TELUGU:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_SINHALA:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If it's indy3 tag, send to USE. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+         planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+       return &_hb_ot_complex_shaper_default;
+      else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
+       return &_hb_ot_complex_shaper_use;
+      else
+       return &_hb_ot_complex_shaper_indic;
+
+    case HB_SCRIPT_KHMER:
+       return &_hb_ot_complex_shaper_khmer;
+
+    case HB_SCRIPT_MYANMAR:
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If designer designed for 'mymr' tag, also send to default
+       * shaper.  That's tag used from before Myanmar shaping spec
+       * was developed.  The shaping spec uses 'mym2' tag. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+         planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+         planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
+       return &_hb_ot_complex_shaper_default;
+      else
+       return &_hb_ot_complex_shaper_myanmar;
+
+
+    /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+    case HB_SCRIPT_MYANMAR_ZAWGYI:
+
+      return &_hb_ot_complex_shaper_myanmar_zawgyi;
+
+
+    /* Unicode-2.0 additions */
+    case HB_SCRIPT_TIBETAN:
+
+    /* Unicode-3.0 additions */
+    //case HB_SCRIPT_MONGOLIAN:
+    //case HB_SCRIPT_SINHALA:
+
+    /* Unicode-3.2 additions */
+    case HB_SCRIPT_BUHID:
+    case HB_SCRIPT_HANUNOO:
+    case HB_SCRIPT_TAGALOG:
+    case HB_SCRIPT_TAGBANWA:
+
+    /* Unicode-4.0 additions */
+    case HB_SCRIPT_LIMBU:
+    case HB_SCRIPT_TAI_LE:
+
+    /* Unicode-4.1 additions */
+    case HB_SCRIPT_BUGINESE:
+    case HB_SCRIPT_KHAROSHTHI:
+    case HB_SCRIPT_SYLOTI_NAGRI:
+    case HB_SCRIPT_TIFINAGH:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_BALINESE:
+    //case HB_SCRIPT_NKO:
+    //case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-5.1 additions */
+    case HB_SCRIPT_CHAM:
+    case HB_SCRIPT_KAYAH_LI:
+    case HB_SCRIPT_LEPCHA:
+    case HB_SCRIPT_REJANG:
+    case HB_SCRIPT_SAURASHTRA:
+    case HB_SCRIPT_SUNDANESE:
+
+    /* Unicode-5.2 additions */
+    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
+    case HB_SCRIPT_JAVANESE:
+    case HB_SCRIPT_KAITHI:
+    case HB_SCRIPT_MEETEI_MAYEK:
+    case HB_SCRIPT_TAI_THAM:
+    case HB_SCRIPT_TAI_VIET:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_BATAK:
+    case HB_SCRIPT_BRAHMI:
+    //case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-6.1 additions */
+    case HB_SCRIPT_CHAKMA:
+    case HB_SCRIPT_SHARADA:
+    case HB_SCRIPT_TAKRI:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_DUPLOYAN:
+    case HB_SCRIPT_GRANTHA:
+    case HB_SCRIPT_KHOJKI:
+    case HB_SCRIPT_KHUDAWADI:
+    case HB_SCRIPT_MAHAJANI:
+    //case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_MODI:
+    case HB_SCRIPT_PAHAWH_HMONG:
+    //case HB_SCRIPT_PSALTER_PAHLAVI:
+    case HB_SCRIPT_SIDDHAM:
+    case HB_SCRIPT_TIRHUTA:
+
+    /* Unicode-8.0 additions */
+    case HB_SCRIPT_AHOM:
+
+    /* Unicode-9.0 additions */
+    //case HB_SCRIPT_ADLAM:
+    case HB_SCRIPT_BHAIKSUKI:
+    case HB_SCRIPT_MARCHEN:
+    case HB_SCRIPT_NEWA:
+
+    /* Unicode-10.0 additions */
+    case HB_SCRIPT_MASARAM_GONDI:
+    case HB_SCRIPT_SOYOMBO:
+    case HB_SCRIPT_ZANABAZAR_SQUARE:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_DOGRA:
+    case HB_SCRIPT_GUNJALA_GONDI:
+    //case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_MAKASAR:
+    //case HB_SCRIPT_SOGDIAN:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       * Note that for some simple scripts, there may not be *any*
+       * GSUB/GPOS needed, so there may be no scripts found! */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+         planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+       return &_hb_ot_complex_shaper_default;
+      else
+       return &_hb_ot_complex_shaper_use;
+  }
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_HH */
diff --git a/src/hb-ot-shape-fallback-private.hh b/src/hb-ot-shape-fallback-private.hh
deleted file mode 100644 (file)
index e134224..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-#define HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                                                hb_font_t *font,
-                                                hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
-                                                                   hb_font_t *font,
-                                                                   hb_buffer_t  *buffer);
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
-                                            hb_font_t *font,
-                                            hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
-                                              hb_font_t *font,
-                                              hb_buffer_t  *buffer);
-
-
-#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
index fbf31ab..f9d4a75 100644 (file)
@@ -24,8 +24,8 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-kern.hh"
 
 static unsigned int
 recategorize_combining_class (hb_codepoint_t u,
@@ -162,9 +162,9 @@ recategorize_combining_class (hb_codepoint_t u,
 }
 
 void
-_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
-                                                  hb_font_t *font HB_UNUSED,
-                                                  hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                                       hb_font_t *font HB_UNUSED,
+                                                       hb_buffer_t  *buffer)
 {
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -180,19 +180,25 @@ _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *pla
 static void
 zero_mark_advances (hb_buffer_t *buffer,
                    unsigned int start,
-                   unsigned int end)
+                   unsigned int end,
+                   bool adjust_offsets_when_zeroing)
 {
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = start; i < end; i++)
     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
     {
+      if (adjust_offsets_when_zeroing)
+      {
+       buffer->pos[i].x_offset -= buffer->pos[i].x_advance;
+       buffer->pos[i].y_offset -= buffer->pos[i].y_advance;
+      }
       buffer->pos[i].x_advance = 0;
       buffer->pos[i].y_advance = 0;
     }
 }
 
 static inline void
-position_mark (const hb_ot_shape_plan_t *plan,
+position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED,
               hb_font_t *font,
               hb_buffer_t  *buffer,
               hb_glyph_extents_t &base_extents,
@@ -303,7 +309,8 @@ position_around_base (const hb_ot_shape_plan_t *plan,
                      hb_font_t *font,
                      hb_buffer_t  *buffer,
                      unsigned int base,
-                     unsigned int end)
+                     unsigned int end,
+                     bool adjust_offsets_when_zeroing)
 {
   hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
 
@@ -314,11 +321,15 @@ position_around_base (const hb_ot_shape_plan_t *plan,
                                &base_extents))
   {
     /* If extents don't work, zero marks and go home. */
-    zero_mark_advances (buffer, base + 1, end);
+    zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
     return;
   }
-  base_extents.x_bearing += buffer->pos[base].x_offset;
   base_extents.y_bearing += buffer->pos[base].y_offset;
+  /* Use horizontal advance for horizontal positioning.
+   * Generally a better idea.  Also works for zero-ink glyphs.  See:
+   * https://github.com/harfbuzz/harfbuzz/issues/1532 */
+  base_extents.x_bearing = 0;
+  base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint);
 
   unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
   /* Use integer for num_lig_components such that it doesn't convert to unsigned
@@ -394,7 +405,8 @@ position_cluster (const hb_ot_shape_plan_t *plan,
                  hb_font_t *font,
                  hb_buffer_t  *buffer,
                  unsigned int start,
-                 unsigned int end)
+                 unsigned int end,
+                 bool adjust_offsets_when_zeroing)
 {
   if (end - start < 2)
     return;
@@ -410,16 +422,17 @@ position_cluster (const hb_ot_shape_plan_t *plan,
        if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
          break;
 
-      position_around_base (plan, font, buffer, i, j);
+      position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
 
       i = j - 1;
     }
 }
 
 void
-_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                               hb_font_t *font,
-                               hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                    hb_font_t *font,
+                                    hb_buffer_t  *buffer,
+                                    bool adjust_offsets_when_zeroing)
 {
   _hb_buffer_assert_gsubgpos_vars (buffer);
 
@@ -428,81 +441,66 @@ _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 1; i < count; i++)
     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
-      position_cluster (plan, font, buffer, start, i);
+      position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
       start = i;
     }
-  position_cluster (plan, font, buffer, start, count);
+  position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
 }
 
 
-/* Performs old-style TrueType kerning. */
+struct hb_ot_shape_fallback_kern_driver_t
+{
+  hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
+                                     hb_buffer_t *buffer) :
+    font (font_), direction (buffer->props.direction) {}
+
+  hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
+  {
+    hb_position_t kern = 0;
+    font->get_glyph_kerning_for_direction (first, second,
+                                          direction,
+                                          &kern, &kern);
+    return kern;
+  }
+
+  hb_font_t *font;
+  hb_direction_t direction;
+};
+
+/* Performs font-assisted kerning. */
 void
 _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
                            hb_font_t *font,
-                           hb_buffer_t  *buffer)
+                           hb_buffer_t *buffer)
 {
-  if (!plan->has_kern) return;
-
-  OT::hb_ot_apply_context_t c (1, font, buffer);
-  c.set_lookup_mask (plan->kern_mask);
-  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
-  skippy_iter.init (&c);
-
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  for (unsigned int idx = 0; idx < count;)
-  {
-    skippy_iter.reset (idx, 1);
-    if (!skippy_iter.next ())
-    {
-      idx++;
-      continue;
-    }
+  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
+      !font->has_glyph_h_kerning_func () :
+      !font->has_glyph_v_kerning_func ())
+    return;
 
-    hb_position_t x_kern, y_kern;
-    font->get_glyph_kerning_for_direction (info[idx].codepoint,
-                                          info[skippy_iter.idx].codepoint,
-                                          buffer->props.direction,
-                                          &x_kern, &y_kern);
+  bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
 
-    if (x_kern)
-    {
-      hb_position_t kern1 = x_kern >> 1;
-      hb_position_t kern2 = x_kern - kern1;
-      pos[idx].x_advance += kern1;
-      pos[skippy_iter.idx].x_advance += kern2;
-      pos[skippy_iter.idx].x_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
+  if (reverse)
+    buffer->reverse ();
 
-    if (y_kern)
-    {
-      hb_position_t kern1 = y_kern >> 1;
-      hb_position_t kern2 = y_kern - kern1;
-      pos[idx].y_advance += kern1;
-      pos[skippy_iter.idx].y_advance += kern2;
-      pos[skippy_iter.idx].y_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
+  hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
+  OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
+  machine.kern (font, buffer, plan->kern_mask, false);
 
-    idx = skippy_iter.idx;
-  }
+  if (reverse)
+    buffer->reverse ();
 }
 
 
 /* Adjusts width of various spaces. */
 void
-_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
                              hb_font_t *font,
                              hb_buffer_t  *buffer)
 {
-  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-    return;
-
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
+  bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
@@ -523,27 +521,40 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
        case t::SPACE_EM_5:
        case t::SPACE_EM_6:
        case t::SPACE_EM_16:
-         pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
+         if (horizontal)
+           pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type;
+         else
+           pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type;
          break;
 
        case t::SPACE_4_EM_18:
-         pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
+         if (horizontal)
+           pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18;
+         else
+           pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18;
          break;
 
        case t::SPACE_FIGURE:
          for (char u = '0'; u <= '9'; u++)
            if (font->get_nominal_glyph (u, &glyph))
            {
-             pos[i].x_advance = font->get_glyph_h_advance (glyph);
+             if (horizontal)
+               pos[i].x_advance = font->get_glyph_h_advance (glyph);
+             else
+               pos[i].y_advance = font->get_glyph_v_advance (glyph);
              break;
            }
          break;
 
        case t::SPACE_PUNCTUATION:
-         if (font->get_nominal_glyph ('.', &glyph))
-           pos[i].x_advance = font->get_glyph_h_advance (glyph);
-         else if (font->get_nominal_glyph (',', &glyph))
-           pos[i].x_advance = font->get_glyph_h_advance (glyph);
+         if (font->get_nominal_glyph ('.', &glyph) ||
+             font->get_nominal_glyph (',', &glyph))
+         {
+           if (horizontal)
+             pos[i].x_advance = font->get_glyph_h_advance (glyph);
+           else
+             pos[i].y_advance = font->get_glyph_v_advance (glyph);
+         }
          break;
 
        case t::SPACE_NARROW:
@@ -552,7 +563,10 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
           * However, in my testing, many fonts have their regular space being about that
           * size.  To me, a percentage of the space width makes more sense.  Half is as
           * good as any. */
-         pos[i].x_advance /= 2;
+         if (horizontal)
+           pos[i].x_advance /= 2;
+         else
+           pos[i].y_advance /= 2;
          break;
       }
     }
diff --git a/src/hb-ot-shape-fallback.hh b/src/hb-ot-shape-fallback.hh
new file mode 100644 (file)
index 0000000..5faf5f2
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_FALLBACK_HH
+#define HB_OT_SHAPE_FALLBACK_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                                     hb_font_t *font,
+                                                     hb_buffer_t  *buffer,
+                                                     bool adjust_offsets_when_zeroing);
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
+                                                                        hb_font_t *font,
+                                                                        hb_buffer_t  *buffer);
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
+                                            hb_font_t *font,
+                                            hb_buffer_t  *buffer);
+
+HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+                                              hb_font_t *font,
+                                              hb_buffer_t  *buffer);
+
+
+#endif /* HB_OT_SHAPE_FALLBACK_HH */
diff --git a/src/hb-ot-shape-normalize-private.hh b/src/hb-ot-shape-normalize-private.hh
deleted file mode 100644 (file)
index c744e26..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-#define HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* buffer var allocations, used during the normalization process */
-#define glyph_index()  var1.u32
-
-struct hb_ot_shape_plan_t;
-
-enum hb_ot_shape_normalization_mode_t {
-  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
-  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */
-
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS
-};
-
-HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
-                                        hb_buffer_t *buffer,
-                                        hb_font_t *font);
-
-
-struct hb_ot_shape_normalize_context_t
-{
-  const hb_ot_shape_plan_t *plan;
-  hb_buffer_t *buffer;
-  hb_font_t *font;
-  hb_unicode_funcs_t *unicode;
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                    hb_codepoint_t  ab,
-                    hb_codepoint_t *a,
-                    hb_codepoint_t *b);
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                  hb_codepoint_t  a,
-                  hb_codepoint_t  b,
-                  hb_codepoint_t *ab);
-};
-
-
-#endif /* HB_OT_SHAPE_NORMALIZE_PRIVATE_HH */
index 358450e..82bb24b 100644 (file)
@@ -24,9 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-normalize-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape-normalize.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape.hh"
 
 
 /*
@@ -213,17 +213,19 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
 }
 
 static inline void
-handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
+handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
+                                  unsigned int end,
+                                  bool short_circuit HB_UNUSED)
 {
   /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
   hb_buffer_t * const buffer = c->buffer;
   hb_font_t * const font = c->font;
   for (; buffer->idx < end - 1 && buffer->successful;) {
     if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
-      /* The next two lines are some ugly lines... But work. */
       if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
       {
-       buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
+       hb_codepoint_t unicode = buffer->cur().codepoint;
+       buffer->replace_glyphs (2, 1, &unicode);
       }
       else
       {
@@ -264,15 +266,6 @@ decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned
     decompose_current_character (c, short_circuit);
 }
 
-static inline void
-decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
-{
-  if (likely (c->buffer->idx + 1 == end))
-    decompose_current_character (c, might_short_circuit);
-  else
-    decompose_multi_char_cluster (c, end, always_short_circuit);
-}
-
 
 static int
 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
@@ -294,6 +287,16 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
   _hb_buffer_assert_unicode_vars (buffer);
 
   hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
+  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO)
+  {
+    if (plan->has_gpos_mark)
+      // https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920
+      //mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+    else
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+  }
+
   const hb_ot_shape_normalize_context_t c = {
     plan,
     buffer,
@@ -318,105 +321,81 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
 
   /* First round, decompose */
 
-  buffer->clear_output ();
-  count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+  bool all_simple = true;
   {
-    unsigned int end;
-    for (end = buffer->idx + 1; end < count; end++)
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
-        break;
+    buffer->clear_output ();
+    count = buffer->len;
+    buffer->idx = 0;
+    do
+    {
+      unsigned int end;
+      for (end = buffer->idx + 1; end < count; end++)
+       if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+         break;
 
-    decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
-  }
-  buffer->swap_buffers ();
+      if (end < count)
+       end--; /* Leave one base for the marks to cluster with. */
 
+      /* From idx to end are simple clusters. */
+      if (might_short_circuit)
+      {
+        unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
+                                                     &buffer->cur().codepoint,
+                                                     sizeof (buffer->info[0]),
+                                                     &buffer->cur().glyph_index(),
+                                                     sizeof (buffer->info[0]));
+       buffer->next_glyphs (done);
+      }
+      while (buffer->idx < end && buffer->successful)
+       decompose_current_character (&c, might_short_circuit);
 
-  /* Second round, reorder (inplace) */
+      if (buffer->idx == count || !buffer->successful)
+       break;
 
-  count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
-      continue;
+      all_simple = false;
 
-    unsigned int end;
-    for (end = i + 1; end < count; end++)
-      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
-        break;
+      /* Find all the marks now. */
+      for (end = buffer->idx + 1; end < count; end++)
+       if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+         break;
 
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
-      i = end;
-      continue;
+      /* idx to end is one non-simple cluster. */
+      decompose_multi_char_cluster (&c, end, always_short_circuit);
     }
-
-    buffer->sort (i, end, compare_combining_class);
-
-    if (plan->shaper->reorder_marks)
-      plan->shaper->reorder_marks (plan, buffer, i, end);
-
-    i = end;
+    while (buffer->idx < count && buffer->successful);
+    buffer->swap_buffers ();
   }
 
 
-  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
-      mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
-    return;
-
-  /* Third round, recompose */
-
-  /* As noted in the comment earlier, we don't try to combine
-   * ccc=0 chars with their previous Starter. */
+  /* Second round, reorder (inplace) */
 
-  buffer->clear_output ();
-  count = buffer->len;
-  unsigned int starter = 0;
-  buffer->next_glyph ();
-  while (buffer->idx < count && buffer->successful)
+  if (!all_simple)
   {
-    hb_codepoint_t composed, glyph;
-    if (/* We don't try to compose a non-mark character with it's preceding starter.
-        * This is both an optimization to avoid trying to compose every two neighboring
-        * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
-        * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
-       HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
+    count = buffer->len;
+    for (unsigned int i = 0; i < count; i++)
     {
-      if (/* If there's anything between the starter and this char, they should have CCC
-          * smaller than this character's. */
-         (starter == buffer->out_len - 1 ||
-          info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
-         /* And compose. */
-         c.compose (&c,
-                    buffer->out_info[starter].codepoint,
-                    buffer->cur().codepoint,
-                    &composed) &&
-         /* And the font has glyph for the composite. */
-         font->get_nominal_glyph (composed, &glyph))
-      {
-       /* Composes. */
-       buffer->next_glyph (); /* Copy to out-buffer. */
-       if (unlikely (!buffer->successful))
-         return;
-       buffer->merge_out_clusters (starter, buffer->out_len);
-       buffer->out_len--; /* Remove the second composable. */
-       /* Modify starter and carry on. */
-       buffer->out_info[starter].codepoint = composed;
-       buffer->out_info[starter].glyph_index() = glyph;
-       _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
+       continue;
+
+      unsigned int end;
+      for (end = i + 1; end < count; end++)
+       if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
+         break;
 
+      /* We are going to do a O(n^2).  Only do this if the sequence is short. */
+      if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+       i = end;
        continue;
       }
-    }
 
-    /* Blocked, or doesn't compose. */
-    buffer->next_glyph ();
+      buffer->sort (i, end, compare_combining_class);
 
-    if (info_cc (buffer->prev()) == 0)
-      starter = buffer->out_len - 1;
-  }
-  buffer->swap_buffers ();
+      if (plan->shaper->reorder_marks)
+       plan->shaper->reorder_marks (plan, buffer, i, end);
 
+      i = end;
+    }
+  }
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
   {
     /* For all CGJ, check if it prevented any reordering at all.
@@ -430,4 +409,63 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
        _hb_glyph_info_unhide (&buffer->info[i]);
       }
   }
+
+
+  /* Third round, recompose */
+
+  if (!all_simple &&
+      (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
+       mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
+  {
+    /* As noted in the comment earlier, we don't try to combine
+     * ccc=0 chars with their previous Starter. */
+
+    buffer->clear_output ();
+    count = buffer->len;
+    unsigned int starter = 0;
+    buffer->next_glyph ();
+    while (buffer->idx < count && buffer->successful)
+    {
+      hb_codepoint_t composed, glyph;
+      if (/* We don't try to compose a non-mark character with it's preceding starter.
+          * This is both an optimization to avoid trying to compose every two neighboring
+          * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
+          * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
+         HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
+      {
+       if (/* If there's anything between the starter and this char, they should have CCC
+            * smaller than this character's. */
+           (starter == buffer->out_len - 1 ||
+            info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
+           /* And compose. */
+           c.compose (&c,
+                      buffer->out_info[starter].codepoint,
+                      buffer->cur().codepoint,
+                      &composed) &&
+           /* And the font has glyph for the composite. */
+           font->get_nominal_glyph (composed, &glyph))
+       {
+         /* Composes. */
+         buffer->next_glyph (); /* Copy to out-buffer. */
+         if (unlikely (!buffer->successful))
+           return;
+         buffer->merge_out_clusters (starter, buffer->out_len);
+         buffer->out_len--; /* Remove the second composable. */
+         /* Modify starter and carry on. */
+         buffer->out_info[starter].codepoint = composed;
+         buffer->out_info[starter].glyph_index() = glyph;
+         _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+
+         continue;
+       }
+      }
+
+      /* Blocked, or doesn't compose. */
+      buffer->next_glyph ();
+
+      if (info_cc (buffer->prev()) == 0)
+       starter = buffer->out_len - 1;
+    }
+    buffer->swap_buffers ();
+  }
 }
diff --git a/src/hb-ot-shape-normalize.hh b/src/hb-ot-shape-normalize.hh
new file mode 100644 (file)
index 0000000..04f1a80
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_NORMALIZE_HH
+#define HB_OT_SHAPE_NORMALIZE_HH
+
+#include "hb.hh"
+
+
+/* buffer var allocations, used during the normalization process */
+#define glyph_index()  var1.u32
+
+struct hb_ot_shape_plan_t;
+
+enum hb_ot_shape_normalization_mode_t {
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* Never composes base-to-base */
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */
+
+  HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, /* See hb-ot-shape-normalize.cc for logic. */
+  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_AUTO
+};
+
+HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
+                                        hb_buffer_t *buffer,
+                                        hb_font_t *font);
+
+
+struct hb_ot_shape_normalize_context_t
+{
+  const hb_ot_shape_plan_t *plan;
+  hb_buffer_t *buffer;
+  hb_font_t *font;
+  hb_unicode_funcs_t *unicode;
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                    hb_codepoint_t  ab,
+                    hb_codepoint_t *a,
+                    hb_codepoint_t *b);
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                  hb_codepoint_t  a,
+                  hb_codepoint_t  b,
+                  hb_codepoint_t *ab);
+};
+
+
+#endif /* HB_OT_SHAPE_NORMALIZE_HH */
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
deleted file mode 100644 (file)
index d689826..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright © 2010  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_PRIVATE_HH
-#define HB_OT_SHAPE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-map-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-
-struct hb_ot_shape_plan_t
-{
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_t map;
-  const void *data;
-  hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
-  hb_mask_t kern_mask;
-  unsigned int has_frac : 1;
-  unsigned int has_kern : 1;
-  unsigned int has_mark : 1;
-
-  inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
-  {
-    unsigned int table_index;
-    switch (table_tag) {
-      case HB_OT_TAG_GSUB: table_index = 0; break;
-      case HB_OT_TAG_GPOS: table_index = 1; break;
-      default: return;
-    }
-    map.collect_lookups (table_index, lookups);
-  }
-  inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
-  inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
-
-  void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-    map.init ();
-  }
-  void fini (void) {
-    map.fini ();
-  }
-};
-
-struct hb_ot_shape_planner_t
-{
-  /* In the order that they are filled in. */
-  hb_face_t *face;
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_builder_t map;
-
-  hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) :
-                        face (master_plan->face_unsafe),
-                        props (master_plan->props),
-                        shaper (nullptr),
-                        map (face, &props) {}
-
-  inline void compile (hb_ot_shape_plan_t &plan,
-                      const int          *coords,
-                      unsigned int        num_coords)
-  {
-    plan.props = props;
-    plan.shaper = shaper;
-    map.compile (plan.map, coords, num_coords);
-
-    plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
-    plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
-    plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
-    plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
-
-    plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
-                                       HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
-
-    plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
-    plan.has_kern = !!plan.kern_mask;
-    plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
-  }
-
-  private:
-  HB_DISALLOW_COPY_AND_ASSIGN (hb_ot_shape_planner_t);
-};
-
-
-#endif /* HB_OT_SHAPE_PRIVATE_HH */
index 36e0bf9..e9d97c9 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER ot
-#define hb_ot_shaper_face_data_t hb_ot_layout_t
-#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-unicode-private.hh"
-#include "hb-set-private.hh"
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-//#include "hb-aat-layout-private.hh"
-
-static hb_tag_t common_features[] = {
-  HB_TAG('c','c','m','p'),
-  HB_TAG('l','o','c','l'),
-  HB_TAG('m','a','r','k'),
-  HB_TAG('m','k','m','k'),
-  HB_TAG('r','l','i','g'),
-};
+#include "hb-shaper-impl.hh"
+
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-ot-shape-normalize.hh"
+
+#include "hb-ot-face.hh"
+
+#include "hb-set.hh"
+
+#include "hb-aat-layout.hh"
+
+
+/**
+ * SECTION:hb-ot-shape
+ * @title: hb-ot-shape
+ * @short_description: OpenType shaping support
+ * @include: hb-ot.h
+ *
+ * Support functions for OpenType shaping related queries.
+ **/
+
+
+static void
+hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
+                             const hb_feature_t             *user_features,
+                             unsigned int                    num_user_features);
+
+static bool
+_hb_apply_morx (hb_face_t *face)
+{
+  if (hb_options ().aat &&
+      hb_aat_layout_has_substitution (face))
+    return true;
+
+  /* Ignore empty GSUB tables. */
+  return (!hb_ot_layout_has_substitution (face) ||
+         !hb_ot_layout_table_get_script_tags (face,
+                                              HB_OT_TAG_GSUB,
+                                              0, nullptr, nullptr)) &&
+        hb_aat_layout_has_substitution (face);
+}
+
+hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *face,
+                                             const hb_segment_properties_t *props) :
+                                               face (face),
+                                               props (*props),
+                                               map (face, props),
+                                               aat_map (face, props),
+                                               apply_morx (_hb_apply_morx (face))
+{
+  shaper = hb_ot_shape_complex_categorize (this);
+
+  script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
+  script_fallback_mark_positioning = shaper->fallback_position;
+
+  if (apply_morx)
+    shaper = &_hb_ot_complex_shaper_default;
+}
+
+void
+hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+                               const hb_ot_shape_plan_key_t &key)
+{
+  plan.props = props;
+  plan.shaper = shaper;
+  map.compile (plan.map, key);
+  if (apply_morx)
+    aat_map.compile (plan.aat_map);
+
+  plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
+  plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
+  plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
+  plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
+  plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
+  hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
+                     HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
+  plan.kern_mask = plan.map.get_mask (kern_tag);
+  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
+
+  plan.requested_kerning = !!plan.kern_mask;
+  plan.requested_tracking = !!plan.trak_mask;
+  bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  bool disable_gpos = plan.shaper->gpos_tag &&
+                     plan.shaper->gpos_tag != plan.map.chosen_script[1];
+
+  /*
+   * Decide who provides glyph classes. GDEF or Unicode.
+   */
+
+  if (!hb_ot_layout_has_glyph_classes (face))
+    plan.fallback_glyph_classes = true;
+
+  /*
+   * Decide who does substitutions. GSUB, morx, or fallback.
+   */
+
+  plan.apply_morx = apply_morx;
+
+  /*
+   * Decide who does positioning. GPOS, kerx, kern, or fallback.
+   */
+
+  if (hb_options ().aat && hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+  else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
+    plan.apply_gpos = true;
+  else if (hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+
+  if (!plan.apply_kerx && !has_gpos_kern)
+  {
+    /* Apparently Apple applies kerx if GPOS kern was not applied. */
+    if (hb_aat_layout_has_positioning (face))
+      plan.apply_kerx = true;
+    else if (hb_ot_layout_has_kerning (face))
+      plan.apply_kern = true;
+  }
+
+  plan.zero_marks = script_zero_marks &&
+                   !plan.apply_kerx &&
+                   (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
+  plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
+
+  plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
+                                             !plan.apply_kerx &&
+                                             (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
+
+  plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
+                                  script_fallback_mark_positioning;
+
+  /* Currently we always apply trak. */
+  plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
+}
+
+bool
+hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
+                          const hb_shape_plan_key_t     *key)
+{
+  map.init ();
+  aat_map.init ();
+
+  hb_ot_shape_planner_t planner (face,
+                                &key->props);
+
+  hb_ot_shape_collect_features (&planner,
+                               key->user_features,
+                               key->num_user_features);
+
+  planner.compile (*this, key->ot);
+
+  if (shaper->data_create)
+  {
+    data = shaper->data_create (this);
+    if (unlikely (!data))
+      return false;
+  }
+
+  return true;
+}
+
+void
+hb_ot_shape_plan_t::fini ()
+{
+  if (shaper->data_destroy)
+    shaper->data_destroy (const_cast<void *> (data));
+
+  map.fini ();
+  aat_map.fini ();
+}
+
+void
+hb_ot_shape_plan_t::substitute (hb_font_t   *font,
+                               hb_buffer_t *buffer) const
+{
+  if (unlikely (apply_morx))
+    hb_aat_layout_substitute (this, font, buffer);
+  else
+    map.substitute (this, font, buffer);
+}
+
+void
+hb_ot_shape_plan_t::position (hb_font_t   *font,
+                             hb_buffer_t *buffer) const
+{
+  if (this->apply_gpos)
+    map.position (this, font, buffer);
+  else if (this->apply_kerx)
+    hb_aat_layout_position (this, font, buffer);
+  else if (this->apply_kern)
+    hb_ot_layout_kern (this, font, buffer);
+  else
+    _hb_ot_shape_fallback_kern (this, font, buffer);
 
+  if (this->apply_trak)
+    hb_aat_layout_track (this, font, buffer);
+}
 
-static hb_tag_t horizontal_features[] = {
-  HB_TAG('c','a','l','t'),
-  HB_TAG('c','l','i','g'),
-  HB_TAG('c','u','r','s'),
-  HB_TAG('k','e','r','n'),
-  HB_TAG('l','i','g','a'),
-  HB_TAG('r','c','l','t'),
+
+static const hb_ot_map_feature_t
+common_features[] =
+{
+  {HB_TAG('c','c','m','p'), F_GLOBAL},
+  {HB_TAG('l','o','c','l'), F_GLOBAL},
+  {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','l','i','g'), F_GLOBAL},
 };
 
 
+static const hb_ot_map_feature_t
+horizontal_features[] =
+{
+  {HB_TAG('c','a','l','t'), F_GLOBAL},
+  {HB_TAG('c','l','i','g'), F_GLOBAL},
+  {HB_TAG('c','u','r','s'), F_GLOBAL},
+  {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
+  {HB_TAG('l','i','g','a'), F_GLOBAL},
+  {HB_TAG('r','c','l','t'), F_GLOBAL},
+};
 
 static void
 hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
-                             const hb_segment_properties_t  *props,
                              const hb_feature_t             *user_features,
                              unsigned int                    num_user_features)
 {
   hb_ot_map_builder_t *map = &planner->map;
 
-  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
+  map->enable_feature (HB_TAG('r','v','r','n'));
   map->add_gsub_pause (nullptr);
 
-  switch (props->direction) {
+  switch (planner->props.direction) {
     case HB_DIRECTION_LTR:
-      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
-      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
+      map->enable_feature (HB_TAG ('l','t','r','a'));
+      map->enable_feature (HB_TAG ('l','t','r','m'));
       break;
     case HB_DIRECTION_RTL:
-      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
-      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
+      map->enable_feature (HB_TAG ('r','t','l','a'));
+      map->add_feature (HB_TAG ('r','t','l','m'));
       break;
     case HB_DIRECTION_TTB:
     case HB_DIRECTION_BTT:
@@ -90,39 +274,62 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
       break;
   }
 
-  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
-  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
-  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
+  /* Automatic fractions. */
+  map->add_feature (HB_TAG ('f','r','a','c'));
+  map->add_feature (HB_TAG ('n','u','m','r'));
+  map->add_feature (HB_TAG ('d','n','o','m'));
+
+  /* Random! */
+  map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
+
+  /* Tracking.  We enable dummy feature here just to allow disabling
+   * AAT 'trak' table using features.
+   * https://github.com/harfbuzz/harfbuzz/issues/1303 */
+  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
+
+  map->enable_feature (HB_TAG ('H','A','R','F'));
 
   if (planner->shaper->collect_features)
     planner->shaper->collect_features (planner);
 
+  map->enable_feature (HB_TAG ('B','U','Z','Z'));
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
-    map->add_global_bool_feature (common_features[i]);
+    map->add_feature (common_features[i]);
 
-  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
+  if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction))
     for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
-      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
-                       (horizontal_features[i] == HB_TAG('k','e','r','n') ?
-                        F_HAS_FALLBACK : F_NONE));
+      map->add_feature (horizontal_features[i]);
   else
   {
     /* We really want to find a 'vert' feature if there's any in the font, no
      * matter which script/langsys it is listed (or not) under.
      * See various bugs referenced from:
      * https://github.com/harfbuzz/harfbuzz/issues/63 */
-    map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
+    map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
   }
 
-  if (planner->shaper->override_features)
-    planner->shaper->override_features (planner);
-
-  for (unsigned int i = 0; i < num_user_features; i++) {
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
     const hb_feature_t *feature = &user_features[i];
-    map->add_feature (feature->tag, feature->value,
-                     (feature->start == 0 && feature->end == (unsigned int) -1) ?
-                      F_GLOBAL : F_NONE);
+    map->add_feature (feature->tag,
+                     (feature->start == HB_FEATURE_GLOBAL_START &&
+                      feature->end == HB_FEATURE_GLOBAL_END) ?  F_GLOBAL : F_NONE,
+                     feature->value);
   }
+
+  if (planner->apply_morx)
+  {
+    hb_aat_map_builder_t *aat_map = &planner->aat_map;
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      const hb_feature_t *feature = &user_features[i];
+      aat_map->add_feature (feature->tag, feature->value);
+    }
+  }
+
+  if (planner->shaper->override_features)
+    planner->shaper->override_features (planner);
 }
 
 
@@ -130,18 +337,17 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
  * shaper face data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
+struct hb_ot_face_data_t {};
 
-hb_ot_shaper_face_data_t *
+hb_ot_face_data_t *
 _hb_ot_shaper_face_data_create (hb_face_t *face)
 {
-  return _hb_ot_layout_create (face);
+  return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
+_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
 {
-  _hb_ot_layout_destroy (data);
 }
 
 
@@ -149,70 +355,21 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
  * shaper font data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
-
-struct hb_ot_shaper_font_data_t {};
+struct hb_ot_font_data_t {};
 
-hb_ot_shaper_font_data_t *
+hb_ot_font_data_t *
 _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
+_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED)
 {
 }
 
 
 /*
- * shaper shape_plan data
- */
-
-hb_ot_shaper_shape_plan_data_t *
-_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
-                                     const hb_feature_t *user_features,
-                                     unsigned int        num_user_features,
-                                     const int          *coords,
-                                     unsigned int        num_coords)
-{
-  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
-  if (unlikely (!plan))
-    return nullptr;
-
-  plan->init ();
-
-  hb_ot_shape_planner_t planner (shape_plan);
-
-  planner.shaper = hb_ot_shape_complex_categorize (&planner);
-
-  hb_ot_shape_collect_features (&planner, &shape_plan->props,
-                               user_features, num_user_features);
-
-  planner.compile (*plan, coords, num_coords);
-
-  if (plan->shaper->data_create) {
-    plan->data = plan->shaper->data_create (plan);
-    if (unlikely (!plan->data))
-      return nullptr;
-  }
-
-  return plan;
-}
-
-void
-_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
-{
-  if (plan->shaper->data_destroy)
-    plan->shaper->data_destroy (const_cast<void *> (plan->data));
-
-  plan->fini ();
-
-  free (plan);
-}
-
-
-/*
  * shaper
  */
 
@@ -226,8 +383,6 @@ struct hb_ot_shape_context_t
   unsigned int        num_user_features;
 
   /* Transient stuff */
-  bool fallback_positioning;
-  bool fallback_glyph_classes;
   hb_direction_t target_direction;
 };
 
@@ -241,10 +396,53 @@ struct hb_ot_shape_context_t
 static void
 hb_set_unicode_props (hb_buffer_t *buffer)
 {
+  /* Implement enough of Unicode Graphemes here that shaping
+   * in reverse-direction wouldn't break graphemes.  Namely,
+   * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
+   * sequences as continuations.  The foreach_grapheme()
+   * macro uses this bit.
+   *
+   * https://www.unicode.org/reports/tr29/#Regex_Definitions
+   */
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
+  {
     _hb_glyph_info_set_unicode_props (&info[i], buffer);
+
+    /* Marks are already set as continuation by the above line.
+     * Handle Emoji_Modifier and ZWJ-continuation. */
+    if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
+                 hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
+    {
+       _hb_glyph_info_set_continuation (&info[i]);
+    }
+    else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
+    {
+      _hb_glyph_info_set_continuation (&info[i]);
+      if (i + 1 < count &&
+         _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
+      {
+        i++;
+       _hb_glyph_info_set_unicode_props (&info[i], buffer);
+       _hb_glyph_info_set_continuation (&info[i]);
+      }
+    }
+    /* Or part of the Other_Grapheme_Extend that is not marks.
+     * As of Unicode 11 that is just:
+     *
+     * 200C          ; Other_Grapheme_Extend # Cf       ZERO WIDTH NON-JOINER
+     * FF9E..FF9F    ; Other_Grapheme_Extend # Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+     * E0020..E007F  ; Other_Grapheme_Extend # Cf  [96] TAG SPACE..CANCEL TAG
+     *
+     * ZWNJ is special, we don't want to merge it as there's no need, and keeping
+     * it separate results in more granular clusters.  Ignore Katakana for now.
+     * Tags are used for Emoji sub-region flag sequences:
+     * https://github.com/harfbuzz/harfbuzz/issues/1556
+     */
+    else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
+      _hb_glyph_info_set_continuation (&info[i]);
+  }
 }
 
 static void
@@ -252,8 +450,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
 {
   if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
       buffer->context_len[0] ||
-      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
-      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+      !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
     return;
 
   if (!font->has_glyph (0x25CCu))
@@ -272,7 +469,6 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
   buffer->output_info (info);
   while (buffer->idx < buffer->len && buffer->successful)
     buffer->next_glyph ();
-
   buffer->swap_buffers ();
 }
 
@@ -282,26 +478,12 @@ hb_form_clusters (hb_buffer_t *buffer)
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
     return;
 
-  /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
-  unsigned int base = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
-               !_hb_glyph_info_is_joiner (&info[i])))
-    {
-      if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-       buffer->merge_clusters (base, i);
-      else
-       buffer->unsafe_to_break (base, i);
-      base = i;
-    }
-  }
   if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-    buffer->merge_clusters (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->merge_clusters (start, end);
   else
-    buffer->unsafe_to_break (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->unsafe_to_break (start, end);
 }
 
 static void
@@ -319,25 +501,17 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
       (HB_DIRECTION_IS_VERTICAL   (direction) &&
        direction != HB_DIRECTION_TTB))
   {
-    /* Same loop as hb_form_clusters().
-     * Since form_clusters() merged clusters already, we don't merge. */
-    unsigned int base = 0;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 1; i < count; i++)
-    {
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
-      {
-       if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-         buffer->merge_clusters (base, i);
-       buffer->reverse_range (base, i);
 
-       base = i;
-      }
-    }
     if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-      buffer->merge_clusters (base, count);
-    buffer->reverse_range (base, count);
+      foreach_grapheme (buffer, start, end)
+      {
+       buffer->merge_clusters (start, end);
+       buffer->reverse_range (start, end);
+      }
+    else
+      foreach_grapheme (buffer, start, end)
+       /* form_clusters() merged clusters already, we don't merge. */
+       buffer->reverse_range (start, end);
 
     buffer->reverse ();
 
@@ -346,10 +520,12 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
 }
 
 
-/* Substitute */
+/*
+ * Substitute
+ */
 
 static inline void
-hb_ot_mirror_chars (hb_ot_shape_context_t *c)
+hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
 {
   if (HB_DIRECTION_IS_FORWARD (c->target_direction))
     return;
@@ -370,7 +546,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
 {
   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
       !c->plan->has_frac)
@@ -420,7 +596,7 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -430,7 +606,7 @@ hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -452,10 +628,8 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
 }
 
 static void
-hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
@@ -471,83 +645,29 @@ hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
 }
 
 static void
-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
+                              hb_font_t   *font)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
     return;
 
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
-  {
-    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
-      break;
-  }
-
-  /* No default-ignorables found; return. */
-  if (i == count)
-    return;
 
-  hb_codepoint_t space;
+  hb_codepoint_t invisible = buffer->invisible;
   if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
-      c->font->get_nominal_glyph (' ', &space))
+      (invisible || font->get_nominal_glyph (' ', &invisible)))
   {
-    /* Replace default-ignorables with a zero-advance space glyph. */
-    for (/*continue*/; i < count; i++)
+    /* Replace default-ignorables with a zero-advance invisible glyph. */
+    for (unsigned int i = 0; i < count; i++)
     {
       if (_hb_glyph_info_is_default_ignorable (&info[i]))
-       info[i].codepoint = space;
+       info[i].codepoint = invisible;
     }
   }
   else
-  {
-    /* Merge clusters and delete default-ignorables.
-     * NOTE! We can't use out-buffer as we have positioning data. */
-    unsigned int j = i;
-    for (; i < count; i++)
-    {
-      if (_hb_glyph_info_is_default_ignorable (&info[i]))
-      {
-       /* Merge clusters.
-        * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
-       unsigned int cluster = info[i].cluster;
-       if (i + 1 < count && cluster == info[i + 1].cluster)
-         continue; /* Cluster survives; do nothing. */
-
-       if (j)
-       {
-         /* Merge cluster backward. */
-         if (cluster < info[j - 1].cluster)
-         {
-           unsigned int mask = info[i].mask;
-           unsigned int old_cluster = info[j - 1].cluster;
-           for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
-             buffer->set_cluster (info[k - 1], cluster, mask);
-         }
-         continue;
-       }
-
-       if (i + 1 < count)
-         buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
-       continue;
-      }
-
-      if (j != i)
-      {
-       info[j] = info[i];
-       pos[j] = pos[i];
-      }
-      j++;
-    }
-    buffer->len = j;
-  }
+    hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
 }
 
 
@@ -564,10 +684,10 @@ hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
 }
 
 static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
+hb_synthesize_glyph_classes (hb_buffer_t *buffer)
 {
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
     hb_ot_layout_glyph_props_flags_t klass;
@@ -590,7 +710,7 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_substitute_default (hb_ot_shape_context_t *c)
+hb_ot_substitute_default (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -603,8 +723,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
   hb_ot_shape_setup_masks (c);
 
   /* This is unfortunate to go here, but necessary... */
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer);
 
   hb_ot_map_glyphs_fast (buffer);
 
@@ -612,23 +732,20 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
+hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
+  if (c->plan->fallback_glyph_classes)
+    hb_synthesize_glyph_classes (c->buffer);
 
   c->plan->substitute (c->font, buffer);
-
-  /* XXX Call morx instead. */
-  //hb_aat_layout_substitute (c->font, c->buffer);
 }
 
 static inline void
-hb_ot_substitute (hb_ot_shape_context_t *c)
+hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
 {
   hb_ot_substitute_default (c);
 
@@ -637,7 +754,21 @@ hb_ot_substitute (hb_ot_shape_context_t *c)
   hb_ot_substitute_complex (c);
 }
 
-/* Position */
+static inline void
+hb_ot_substitute_post (const hb_ot_shape_context_t *c)
+{
+  hb_ot_hide_default_ignorables (c->buffer, c->font);
+  if (c->plan->apply_morx)
+    hb_aat_layout_remove_deleted_glyphs (c->buffer);
+
+  if (c->plan->shaper->postprocess_glyphs)
+    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+}
+
+
+/*
+ * Position
+ */
 
 static inline void
 adjust_mark_offsets (hb_glyph_position_t *pos)
@@ -668,7 +799,7 @@ zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
 }
 
 static inline void
-hb_ot_position_default (hb_ot_shape_context_t *c)
+hb_ot_position_default (const hb_ot_shape_context_t *c)
 {
   hb_direction_t direction = c->buffer->props.direction;
   unsigned int count = c->buffer->len;
@@ -677,8 +808,8 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
 
   if (HB_DIRECTION_IS_HORIZONTAL (direction))
   {
-    for (unsigned int i = 0; i < count; i++)
-      pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
+    c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].x_advance, sizeof(pos[0]));
     /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
@@ -688,9 +819,10 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
   }
   else
   {
+    c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].y_advance, sizeof(pos[0]));
     for (unsigned int i = 0; i < count; i++)
     {
-      pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
       c->font->subtract_glyph_v_origin (info[i].codepoint,
                                        &pos[i].x_offset,
                                        &pos[i].y_offset);
@@ -701,23 +833,22 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
 }
 
 static inline void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
+hb_ot_position_complex (const hb_ot_shape_context_t *c)
 {
   unsigned int count = c->buffer->len;
   hb_glyph_info_t *info = c->buffer->info;
   hb_glyph_position_t *pos = c->buffer->pos;
 
-  /* If the font has no GPOS, AND, no fallback positioning will
-   * happen, AND, direction is forward, then when zeroing mark
-   * widths, we shift the mark with it, such that the mark
-   * is positioned hanging over the previous glyph.  When
+  /* If the font has no GPOS and direction is forward, then when
+   * zeroing mark widths, we shift the mark with it, such that the
+   * mark is positioned hanging over the previous glyph.  When
    * direction is backward we don't shift and it will end up
    * hanging over the next glyph after the final reordering.
-   * If fallback positinoing happens or GPOS is present, we don't
-   * care.
+   *
+   * Note: If fallback positinoing happens, we don't care about
+   * this as it will be overriden.
    */
-  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
-                                    !c->plan->shaper->fallback_position &&
+  bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
                                     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
 
   /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
@@ -731,36 +862,39 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
 
   hb_ot_layout_position_start (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
-
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      break;
-  }
-
-  if (likely (!c->fallback_positioning))
-    c->plan->position (c->font, c->buffer);
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+       break;
+
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+       break;
+    }
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
+  c->plan->position (c->font, c->buffer);
 
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      break;
-  }
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+       break;
+
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+       break;
+    }
 
-  /* Finishing off GPOS has to follow a certain order. */
+  /* Finish off.  Has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
-  hb_ot_zero_width_default_ignorables (c);
+  hb_ot_zero_width_default_ignorables (c->buffer);
+  if (c->plan->apply_morx)
+    hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
 
   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
@@ -769,10 +903,14 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
       c->font->subtract_glyph_h_origin (info[i].codepoint,
                                        &pos[i].x_offset,
                                        &pos[i].y_offset);
+
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
+                                        adjust_offsets_when_zeroing);
 }
 
 static inline void
-hb_ot_position (hb_ot_shape_context_t *c)
+hb_ot_position (const hb_ot_shape_context_t *c)
 {
   c->buffer->clear_positions ();
 
@@ -780,20 +918,10 @@ hb_ot_position (hb_ot_shape_context_t *c)
 
   hb_ot_position_complex (c);
 
-  if (c->fallback_positioning && c->plan->shaper->fallback_position)
-    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
-
   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
     hb_buffer_reverse (c->buffer);
 
-  /* Visual fallback goes here. */
-
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
-
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
-
-  //hb_aat_layout_position (c->font, c->buffer);
 }
 
 static inline void
@@ -829,22 +957,17 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
 {
   c->buffer->deallocate_var_all ();
   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
   {
     c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
                              (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
   {
     c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
                              (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 
-  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
-  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
-  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
-  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
-
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
 
@@ -863,13 +986,9 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
   if (c->plan->shaper->preprocess_text)
     c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
 
-  hb_ot_substitute (c);
+  hb_ot_substitute_pre (c);
   hb_ot_position (c);
-
-  hb_ot_hide_default_ignorables (c);
-
-  if (c->plan->shaper->postprocess_glyphs)
-    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+  hb_ot_substitute_post (c);
 
   hb_propagate_flags (c->buffer);
 
@@ -890,7 +1009,7 @@ _hb_ot_shape (hb_shape_plan_t    *shape_plan,
              const hb_feature_t *features,
              unsigned int        num_features)
 {
-  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
+  hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features};
   hb_ot_shape_internal (&c);
 
   return true;
@@ -907,8 +1026,7 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
                                  hb_tag_t         table_tag,
                                  hb_set_t        *lookup_indexes /* OUT */)
 {
-  /* XXX Does the first part always succeed? */
-  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
+  shape_plan->ot.collect_lookups (table_tag, lookup_indexes);
 }
 
 
diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh
new file mode 100644 (file)
index 0000000..73a11e1
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2010  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_HH
+#define HB_OT_SHAPE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-map.hh"
+#include "hb-aat-map.hh"
+
+
+struct hb_ot_shape_plan_key_t
+{
+  unsigned int variations_index[2];
+
+  void init (hb_face_t   *face,
+                   const int   *coords,
+                   unsigned int num_coords)
+  {
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+      hb_ot_layout_table_find_feature_variations (face,
+                                                 table_tags[table_index],
+                                                 coords,
+                                                 num_coords,
+                                                 &variations_index[table_index]);
+  }
+
+  bool equal (const hb_ot_shape_plan_key_t *other)
+  {
+    return 0 == memcmp (this, other, sizeof (*this));
+  }
+};
+
+
+struct hb_shape_plan_key_t;
+
+struct hb_ot_shape_plan_t
+{
+  hb_segment_properties_t props;
+  const struct hb_ot_complex_shaper_t *shaper;
+  hb_ot_map_t map;
+  hb_aat_map_t aat_map;
+  const void *data;
+  hb_mask_t frac_mask, numr_mask, dnom_mask;
+  hb_mask_t rtlm_mask;
+  hb_mask_t kern_mask;
+  hb_mask_t trak_mask;
+
+  bool requested_kerning : 1;
+  bool requested_tracking : 1;
+  bool has_frac : 1;
+  bool has_gpos_mark : 1;
+  bool zero_marks : 1;
+  bool fallback_glyph_classes : 1;
+  bool fallback_mark_positioning : 1;
+  bool adjust_mark_positioning_when_zeroing : 1;
+
+  bool apply_gpos : 1;
+  bool apply_kerx : 1;
+  bool apply_kern : 1;
+  bool apply_morx : 1;
+  bool apply_trak : 1;
+
+  void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
+  {
+    unsigned int table_index;
+    switch (table_tag) {
+      case HB_OT_TAG_GSUB: table_index = 0; break;
+      case HB_OT_TAG_GPOS: table_index = 1; break;
+      default: return;
+    }
+    map.collect_lookups (table_index, lookups);
+  }
+
+  HB_INTERNAL bool init0 (hb_face_t                     *face,
+                         const hb_shape_plan_key_t     *key);
+  HB_INTERNAL void fini ();
+
+  HB_INTERNAL void substitute (hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (hb_font_t *font, hb_buffer_t *buffer) const;
+};
+
+struct hb_shape_plan_t;
+
+struct hb_ot_shape_planner_t
+{
+  /* In the order that they are filled in. */
+  hb_face_t *face;
+  hb_segment_properties_t props;
+  hb_ot_map_builder_t map;
+  hb_aat_map_builder_t aat_map;
+  bool apply_morx : 1;
+  bool script_zero_marks : 1;
+  bool script_fallback_mark_positioning : 1;
+  const struct hb_ot_complex_shaper_t *shaper;
+
+  HB_INTERNAL hb_ot_shape_planner_t (hb_face_t                     *face,
+                                    const hb_segment_properties_t *props);
+
+  HB_INTERNAL void compile (hb_ot_shape_plan_t           &plan,
+                           const hb_ot_shape_plan_key_t &key);
+};
+
+
+#endif /* HB_OT_SHAPE_HH */
diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh
new file mode 100644 (file)
index 0000000..04a2ee9
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#ifndef HB_OT_STAT_TABLE_HH
+#define HB_OT_STAT_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+
+/*
+ * STAT -- Style Attributes
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
+ */
+#define HB_OT_TAG_STAT HB_TAG('S','T','A','T')
+
+
+namespace OT {
+
+enum
+{
+  OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001,       /* If set, this axis value table
+                                                * provides axis value information
+                                                * that is applicable to other fonts
+                                                * within the same font family. This
+                                                * is used if the other fonts were
+                                                * released earlier and did not include
+                                                * information about values for some axis.
+                                                * If newer versions of the other
+                                                * fonts include the information
+                                                * themselves and are present,
+                                                * then this record is ignored. */
+  ELIDABLE_AXIS_VALUE_NAME = 0x0002            /* If set, it indicates that the axis
+                                                * value represents the “normal” value
+                                                * for the axis and may be omitted when
+                                                * composing name strings. */
+  // Reserved = 0xFFFC                         /* Reserved for future use — set to zero. */
+};
+
+struct AxisValueFormat1
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier — set to 1. */
+  HBUINT16     axisIndex;      /* Zero-base index into the axis record array
+                                * identifying the axis of design variation
+                                * to which the axis value record applies.
+                                * Must be less than designAxisCount. */
+  HBUINT16     flags;          /* Flags — see below for details. */
+  NameID       valueNameID;    /* The name ID for entries in the 'name' table
+                                * that provide a display string for this
+                                * attribute value. */
+  Fixed                value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct AxisValueFormat2
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier — set to 2. */
+  HBUINT16     axisIndex;      /* Zero-base index into the axis record array
+                                * identifying the axis of design variation
+                                * to which the axis value record applies.
+                                * Must be less than designAxisCount. */
+  HBUINT16     flags;          /* Flags — see below for details. */
+  NameID       valueNameID;    /* The name ID for entries in the 'name' table
+                                * that provide a display string for this
+                                * attribute value. */
+  Fixed                nominalValue;   /* A numeric value for this attribute value. */
+  Fixed                rangeMinValue;  /* The minimum value for a range associated
+                                * with the specified name ID. */
+  Fixed                rangeMaxValue;  /* The maximum value for a range associated
+                                * with the specified name ID. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct AxisValueFormat3
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier — set to 3. */
+  HBUINT16     axisIndex;      /* Zero-base index into the axis record array
+                                * identifying the axis of design variation
+                                * to which the axis value record applies.
+                                * Must be less than designAxisCount. */
+  HBUINT16     flags;          /* Flags — see below for details. */
+  NameID       valueNameID;    /* The name ID for entries in the 'name' table
+                                * that provide a display string for this
+                                * attribute value. */
+  Fixed                value;          /* A numeric value for this attribute value. */
+  Fixed                linkedValue;    /* The numeric value for a style-linked mapping
+                                * from this value. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+struct AxisValueRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16     axisIndex;      /* Zero-base index into the axis record array
+                                * identifying the axis to which this value
+                                * applies. Must be less than designAxisCount. */
+  Fixed                value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct AxisValueFormat4
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16     format;         /* Format identifier — set to 4. */
+  HBUINT16     axisCount;      /* The total number of axes contributing to
+                                * this axis-values combination. */
+  HBUINT16     flags;          /* Flags — see below for details. */
+  NameID       valueNameID;    /* The name ID for entries in the 'name' table
+                                * that provide a display string for this
+                                * attribute value. */
+  UnsizedArrayOf<AxisValueRecord>
+               axisValues;     /* Array of AxisValue records that provide the
+                                * combination of axis values, one for each
+                                * contributing axis. */
+  public:
+  DEFINE_SIZE_ARRAY (8, axisValues);
+};
+
+struct AxisValue
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.format)
+    {
+    case 1:  return_trace (likely (u.format1.sanitize (c)));
+    case 2:  return_trace (likely (u.format2.sanitize (c)));
+    case 3:  return_trace (likely (u.format3.sanitize (c)));
+    case 4:  return_trace (likely (u.format4.sanitize (c)));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union
+  {
+  HBUINT16             format;
+  AxisValueFormat1     format1;
+  AxisValueFormat2     format2;
+  AxisValueFormat3     format3;
+  AxisValueFormat4     format4;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct StatAxisRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  Tag          tag;            /* A tag identifying the axis of design variation. */
+  NameID       nameID;         /* The name ID for entries in the 'name' table that
+                                * provide a display string for this axis. */
+  HBUINT16     ordering;       /* A value that applications can use to determine
+                                * primary sorting of face names, or for ordering
+                                * of descriptors when composing family or face names. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct STAT
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                         majorVersion == 1 &&
+                         minorVersion > 0 &&
+                         designAxesOffset.sanitize (c, this, designAxisCount) &&
+                         offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
+  }
+
+  protected:
+  HBUINT16     majorVersion;   /* Major version number of the style attributes
+                                * table — set to 1. */
+  HBUINT16     minorVersion;   /* Minor version number of the style attributes
+                                * table — set to 2. */
+  HBUINT16     designAxisSize; /* The size in bytes of each axis record. */
+  HBUINT16     designAxisCount;/* The number of design axis records. In a
+                                * font with an 'fvar' table, this value must be
+                                * greater than or equal to the axisCount value
+                                * in the 'fvar' table. In all fonts, must
+                                * be greater than zero if axisValueCount
+                                * is greater than zero. */
+  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
+               designAxesOffset;
+                               /* Offset in bytes from the beginning of
+                                * the STAT table to the start of the design
+                                * axes array. If designAxisCount is zero,
+                                * set to zero; if designAxisCount is greater
+                                * than zero, must be greater than zero. */
+  HBUINT16     axisValueCount; /* The number of axis value tables. */
+  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
+               offsetToAxisValueOffsets;
+                               /* Offset in bytes from the beginning of
+                                * the STAT table to the start of the design
+                                * axes value offsets array. If axisValueCount
+                                * is zero, set to zero; if axisValueCount is
+                                * greater than zero, must be greater than zero. */
+  NameID       elidedFallbackNameID;
+                               /* Name ID used as fallback when projection of
+                                * names into a particular font model produces
+                                * a subfamily name containing only elidable
+                                * elements. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_STAT_TABLE_HH */
diff --git a/src/hb-ot-tag-table.hh b/src/hb-ot-tag-table.hh
new file mode 100644 (file)
index 0000000..b7090a0
--- /dev/null
@@ -0,0 +1,2064 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ *   ./gen-tag-table.py languagetags language-subtag-registry
+ *
+ * on files with these headers:
+ *
+ * <meta name="updated_at" content="2018-09-07 07:45 PM" />
+ * File-Date: 2018-08-08
+ */
+
+#ifndef HB_OT_TAG_TABLE_HH
+#define HB_OT_TAG_TABLE_HH
+
+static const LangTag ot_languages[] = {
+  {"aa",       {HB_TAG('A','F','R',' ')}},     /* Afar */
+  {"aae",      {HB_TAG('S','Q','I',' ')}},     /* Arbëreshë Albanian -> Albanian */
+  {"aao",      {HB_TAG('A','R','A',' ')}},     /* Algerian Saharan Arabic -> Arabic */
+  {"aat",      {HB_TAG('S','Q','I',' ')}},     /* Arvanitika Albanian -> Albanian */
+  {"ab",       {HB_TAG('A','B','K',' ')}},     /* Abkhazian */
+  {"abh",      {HB_TAG('A','R','A',' ')}},     /* Tajiki Arabic -> Arabic */
+  {"abq",      {HB_TAG('A','B','A',' ')}},     /* Abaza */
+  {"abv",      {HB_TAG('A','R','A',' ')}},     /* Baharna Arabic -> Arabic */
+  {"acf",      {HB_TAG('F','A','N',' ')}},     /* Saint Lucian Creole French -> French Antillean */
+  {"ach",      {HB_TAG('A','C','H',' ')}},     /* Acoli -> Acholi */
+  {"acm",      {HB_TAG('A','R','A',' ')}},     /* Mesopotamian Arabic -> Arabic */
+  {"acq",      {HB_TAG('A','R','A',' ')}},     /* Ta'izzi-Adeni Arabic -> Arabic */
+  {"acr",      {HB_TAG('A','C','R',' ')}},     /* Achi */
+  {"acw",      {HB_TAG('A','R','A',' ')}},     /* Hijazi Arabic -> Arabic */
+  {"acx",      {HB_TAG('A','R','A',' ')}},     /* Omani Arabic -> Arabic */
+  {"acy",      {HB_TAG('A','R','A',' ')}},     /* Cypriot Arabic -> Arabic */
+  {"ada",      {HB_TAG('D','N','G',' ')}},     /* Adangme -> Dangme */
+  {"adf",      {HB_TAG('A','R','A',' ')}},     /* Dhofari Arabic -> Arabic */
+  {"adp",      {HB_TAG('D','Z','N',' ')}},     /* Adap (retired code) -> Dzongkha */
+  {"ady",      {HB_TAG('A','D','Y',' ')}},     /* Adyghe */
+  {"aeb",      {HB_TAG('A','R','A',' ')}},     /* Tunisian Arabic -> Arabic */
+  {"aec",      {HB_TAG('A','R','A',' ')}},     /* Saidi Arabic -> Arabic */
+  {"af",       {HB_TAG('A','F','K',' ')}},     /* Afrikaans */
+  {"afb",      {HB_TAG('A','R','A',' ')}},     /* Gulf Arabic -> Arabic */
+  {"ahg",      {HB_TAG('A','G','W',' ')}},     /* Qimant -> Agaw */
+  {"aht",      {HB_TAG('A','T','H',' ')}},     /* Ahtena -> Athapaskan */
+  {"aii",      {HB_TAG('S','W','A',' '),       /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+                HB_TAG('S','Y','R',' ')}},     /* Assyrian Neo-Aramaic -> Syriac */
+  {"aio",      {HB_TAG('A','I','O',' ')}},     /* Aiton */
+  {"aiw",      {HB_TAG('A','R','I',' ')}},     /* Aari */
+  {"ajp",      {HB_TAG('A','R','A',' ')}},     /* South Levantine Arabic -> Arabic */
+  {"ak",       {HB_TAG('A','K','A',' '),       /* Akan [macrolanguage] */
+                HB_TAG('T','W','I',' ')}},     /* Akan [macrolanguage] -> Twi */
+  {"aln",      {HB_TAG('S','Q','I',' ')}},     /* Gheg Albanian -> Albanian */
+  {"als",      {HB_TAG('S','Q','I',' ')}},     /* Tosk Albanian -> Albanian */
+  {"alt",      {HB_TAG('A','L','T',' ')}},     /* Southern Altai -> Altai */
+  {"am",       {HB_TAG('A','M','H',' ')}},     /* Amharic */
+  {"amf",      {HB_TAG('H','B','N',' ')}},     /* Hamer-Banna -> Hammer-Banna */
+  {"amw",      {HB_TAG('S','Y','R',' ')}},     /* Western Neo-Aramaic -> Syriac */
+  {"an",       {HB_TAG('A','R','G',' ')}},     /* Aragonese */
+  {"ang",      {HB_TAG('A','N','G',' ')}},     /* Old English (ca. 450-1100) -> Anglo-Saxon */
+  {"apc",      {HB_TAG('A','R','A',' ')}},     /* North Levantine Arabic -> Arabic */
+  {"apd",      {HB_TAG('A','R','A',' ')}},     /* Sudanese Arabic -> Arabic */
+  {"apj",      {HB_TAG('A','T','H',' ')}},     /* Jicarilla Apache -> Athapaskan */
+  {"apk",      {HB_TAG('A','T','H',' ')}},     /* Kiowa Apache -> Athapaskan */
+  {"apl",      {HB_TAG('A','T','H',' ')}},     /* Lipan Apache -> Athapaskan */
+  {"apm",      {HB_TAG('A','T','H',' ')}},     /* Mescalero-Chiricahua Apache -> Athapaskan */
+  {"apw",      {HB_TAG('A','T','H',' ')}},     /* Western Apache -> Athapaskan */
+  {"ar",       {HB_TAG('A','R','A',' ')}},     /* Arabic [macrolanguage] */
+  {"arb",      {HB_TAG('A','R','A',' ')}},     /* Standard Arabic -> Arabic */
+  {"arn",      {HB_TAG('M','A','P',' ')}},     /* Mapudungun */
+  {"arq",      {HB_TAG('A','R','A',' ')}},     /* Algerian Arabic -> Arabic */
+  {"ars",      {HB_TAG('A','R','A',' ')}},     /* Najdi Arabic -> Arabic */
+  {"ary",      {HB_TAG('M','O','R',' ')}},     /* Moroccan Arabic -> Moroccan */
+  {"arz",      {HB_TAG('A','R','A',' ')}},     /* Egyptian Arabic -> Arabic */
+  {"as",       {HB_TAG('A','S','M',' ')}},     /* Assamese */
+  {"ast",      {HB_TAG('A','S','T',' ')}},     /* Asturian */
+  {"ath",      {HB_TAG('A','T','H',' ')}},     /* Athapascan [family] -> Athapaskan */
+  {"atj",      {HB_TAG('R','C','R',' ')}},     /* Atikamekw -> R-Cree */
+  {"atv",      {HB_TAG('A','L','T',' ')}},     /* Northern Altai -> Altai */
+  {"auz",      {HB_TAG('A','R','A',' ')}},     /* Uzbeki Arabic -> Arabic */
+  {"av",       {HB_TAG('A','V','R',' ')}},     /* Avaric -> Avar */
+  {"avl",      {HB_TAG('A','R','A',' ')}},     /* Eastern Egyptian Bedawi Arabic -> Arabic */
+  {"awa",      {HB_TAG('A','W','A',' ')}},     /* Awadhi */
+  {"ay",       {HB_TAG('A','Y','M',' ')}},     /* Aymara [macrolanguage] */
+  {"ayc",      {HB_TAG('A','Y','M',' ')}},     /* Southern Aymara -> Aymara */
+  {"ayh",      {HB_TAG('A','R','A',' ')}},     /* Hadrami Arabic -> Arabic */
+  {"ayl",      {HB_TAG('A','R','A',' ')}},     /* Libyan Arabic -> Arabic */
+  {"ayn",      {HB_TAG('A','R','A',' ')}},     /* Sanaani Arabic -> Arabic */
+  {"ayp",      {HB_TAG('A','R','A',' ')}},     /* North Mesopotamian Arabic -> Arabic */
+  {"ayr",      {HB_TAG('A','Y','M',' ')}},     /* Central Aymara -> Aymara */
+  {"az",       {HB_TAG('A','Z','E',' ')}},     /* Azerbaijani [macrolanguage] */
+  {"azb",      {HB_TAG('A','Z','B',' ')}},     /* South Azerbaijani -> Torki */
+  {"azj",      {HB_TAG('A','Z','E',' ')}},     /* North Azerbaijani -> Azerbaijani */
+  {"ba",       {HB_TAG('B','S','H',' ')}},     /* Bashkir */
+  {"bad",      {HB_TAG('B','A','D','0')}},     /* Banda [family] */
+  {"bai",      {HB_TAG('B','M','L',' ')}},     /* Bamileke [family] */
+  {"bal",      {HB_TAG('B','L','I',' ')}},     /* Baluchi [macrolanguage] */
+  {"ban",      {HB_TAG('B','A','N',' ')}},     /* Balinese */
+  {"bar",      {HB_TAG('B','A','R',' ')}},     /* Bavarian */
+  {"bbc",      {HB_TAG('B','B','C',' ')}},     /* Batak Toba */
+  {"bbz",      {HB_TAG('A','R','A',' ')}},     /* Babalia Creole Arabic -> Arabic */
+  {"bcc",      {HB_TAG('B','L','I',' ')}},     /* Southern Balochi -> Baluchi */
+  {"bci",      {HB_TAG('B','A','U',' ')}},     /* Baoulé -> Baulé */
+  {"bcl",      {HB_TAG('B','I','K',' ')}},     /* Central Bikol -> Bikol */
+  {"bcq",      {HB_TAG('B','C','H',' ')}},     /* Bench */
+  {"bcr",      {HB_TAG('A','T','H',' ')}},     /* Babine -> Athapaskan */
+  {"bdy",      {HB_TAG('B','D','Y',' ')}},     /* Bandjalang */
+  {"be",       {HB_TAG('B','E','L',' ')}},     /* Belarusian -> Belarussian */
+  {"bea",      {HB_TAG('A','T','H',' ')}},     /* Beaver -> Athapaskan */
+  {"beb",      {HB_TAG('B','T','I',' ')}},     /* Bebele -> Beti */
+  {"bem",      {HB_TAG('B','E','M',' ')}},     /* Bemba (Zambia) */
+  {"ber",      {HB_TAG('B','B','R',' ')}},     /* Berber [family] */
+  {"bfq",      {HB_TAG('B','A','D',' ')}},     /* Badaga */
+  {"bft",      {HB_TAG('B','L','T',' ')}},     /* Balti */
+  {"bfu",      {HB_TAG('L','A','H',' ')}},     /* Gahri -> Lahuli */
+  {"bfy",      {HB_TAG('B','A','G',' ')}},     /* Bagheli -> Baghelkhandi */
+  {"bg",       {HB_TAG('B','G','R',' ')}},     /* Bulgarian */
+  {"bgc",      {HB_TAG('B','G','C',' ')}},     /* Haryanvi */
+  {"bgn",      {HB_TAG('B','L','I',' ')}},     /* Western Balochi -> Baluchi */
+  {"bgp",      {HB_TAG('B','L','I',' ')}},     /* Eastern Balochi -> Baluchi */
+  {"bgq",      {HB_TAG('B','G','Q',' ')}},     /* Bagri */
+  {"bgr",      {HB_TAG('Q','I','N',' ')}},     /* Bawm Chin -> Chin */
+  {"bhb",      {HB_TAG('B','H','I',' ')}},     /* Bhili */
+  {"bhi",      {HB_TAG('B','H','I',' ')}},     /* Bhilali -> Bhili */
+  {"bhk",      {HB_TAG('B','I','K',' ')}},     /* Albay Bicolano (retired code) -> Bikol */
+  {"bho",      {HB_TAG('B','H','O',' ')}},     /* Bhojpuri */
+  {"bhr",      {HB_TAG('M','L','G',' ')}},     /* Bara Malagasy -> Malagasy */
+  {"bi",       {HB_TAG('B','I','S',' ')}},     /* Bislama */
+  {"bik",      {HB_TAG('B','I','K',' ')}},     /* Bikol [macrolanguage] */
+  {"bin",      {HB_TAG('E','D','O',' ')}},     /* Edo */
+  {"bjj",      {HB_TAG('B','J','J',' ')}},     /* Kanauji */
+  {"bjn",      {HB_TAG('M','L','Y',' ')}},     /* Banjar -> Malay */
+  {"bjq",      {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+  {"bjt",      {HB_TAG('B','L','N',' ')}},     /* Balanta-Ganja -> Balante */
+  {"bla",      {HB_TAG('B','K','F',' ')}},     /* Siksika -> Blackfoot */
+  {"ble",      {HB_TAG('B','L','N',' ')}},     /* Balanta-Kentohe -> Balante */
+  {"blk",      {HB_TAG('B','L','K',' ')}},     /* Pa'o Karen */
+  {"bln",      {HB_TAG('B','I','K',' ')}},     /* Southern Catanduanes Bikol -> Bikol */
+  {"bm",       {HB_TAG('B','M','B',' ')}},     /* Bambara (Bamanankan) */
+  {"bmm",      {HB_TAG('M','L','G',' ')}},     /* Northern Betsimisaraka Malagasy -> Malagasy */
+  {"bn",       {HB_TAG('B','E','N',' ')}},     /* Bengali */
+  {"bo",       {HB_TAG('T','I','B',' ')}},     /* Tibetan */
+  {"bpy",      {HB_TAG('B','P','Y',' ')}},     /* Bishnupriya -> Bishnupriya Manipuri */
+  {"bqi",      {HB_TAG('L','R','C',' ')}},     /* Bakhtiari -> Luri */
+  {"br",       {HB_TAG('B','R','E',' ')}},     /* Breton */
+  {"bra",      {HB_TAG('B','R','I',' ')}},     /* Braj -> Braj Bhasha */
+  {"brh",      {HB_TAG('B','R','H',' ')}},     /* Brahui */
+  {"brx",      {HB_TAG('B','R','X',' ')}},     /* Bodo (India) */
+  {"bs",       {HB_TAG('B','O','S',' ')}},     /* Bosnian */
+  {"bsk",      {HB_TAG('B','S','K',' ')}},     /* Burushaski */
+  {"btb",      {HB_TAG('B','T','I',' ')}},     /* Beti (Cameroon) (retired code) */
+  {"btj",      {HB_TAG('M','L','Y',' ')}},     /* Bacanese Malay -> Malay */
+  {"bto",      {HB_TAG('B','I','K',' ')}},     /* Rinconada Bikol -> Bikol */
+  {"bts",      {HB_TAG('B','T','S',' ')}},     /* Batak Simalungun */
+  {"bug",      {HB_TAG('B','U','G',' ')}},     /* Buginese -> Bugis */
+  {"bum",      {HB_TAG('B','T','I',' ')}},     /* Bulu (Cameroon) -> Beti */
+  {"bve",      {HB_TAG('M','L','Y',' ')}},     /* Berau Malay -> Malay */
+  {"bvu",      {HB_TAG('M','L','Y',' ')}},     /* Bukit Malay -> Malay */
+  {"bxk",      {HB_TAG('L','U','H',' ')}},     /* Bukusu -> Luyia */
+  {"bxp",      {HB_TAG('B','T','I',' ')}},     /* Bebil -> Beti */
+  {"bxr",      {HB_TAG('R','B','U',' ')}},     /* Russia Buriat -> Russian Buriat */
+  {"byn",      {HB_TAG('B','I','L',' ')}},     /* Bilin -> Bilen */
+  {"byv",      {HB_TAG('B','Y','V',' ')}},     /* Medumba */
+  {"bzc",      {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy -> Malagasy */
+  {"ca",       {HB_TAG('C','A','T',' ')}},     /* Catalan */
+  {"caf",      {HB_TAG('C','R','R',' '),       /* Southern Carrier -> Carrier */
+                HB_TAG('A','T','H',' ')}},     /* Southern Carrier -> Athapaskan */
+  {"cak",      {HB_TAG('C','A','K',' ')}},     /* Kaqchikel */
+  {"cbk",      {HB_TAG('C','B','K',' ')}},     /* Chavacano -> Zamboanga Chavacano */
+  {"cbl",      {HB_TAG('Q','I','N',' ')}},     /* Bualkhaw Chin -> Chin */
+  {"cco",      {HB_TAG('C','C','H','N')}},     /* Comaltepec Chinantec -> Chinantec */
+  {"ccq",      {HB_TAG('A','R','K',' ')}},     /* Chaungtha (retired code) -> Rakhine */
+  {"cdo",      {HB_TAG('Z','H','S',' ')}},     /* Min Dong Chinese -> Chinese Simplified */
+  {"ce",       {HB_TAG('C','H','E',' ')}},     /* Chechen */
+  {"ceb",      {HB_TAG('C','E','B',' ')}},     /* Cebuano */
+  {"cfm",      {HB_TAG('H','A','L',' ')}},     /* Halam (Falam Chin) */
+  {"cgg",      {HB_TAG('C','G','G',' ')}},     /* Chiga */
+  {"ch",       {HB_TAG('C','H','A',' ')}},     /* Chamorro */
+  {"chj",      {HB_TAG('C','C','H','N')}},     /* Ojitlán Chinantec -> Chinantec */
+  {"chk",      {HB_TAG('C','H','K','0')}},     /* Chuukese */
+  {"cho",      {HB_TAG('C','H','O',' ')}},     /* Choctaw */
+  {"chp",      {HB_TAG('C','H','P',' '),       /* Chipewyan */
+                HB_TAG('S','A','Y',' '),       /* Chipewyan -> Sayisi */
+                HB_TAG('A','T','H',' ')}},     /* Chipewyan -> Athapaskan */
+  {"chq",      {HB_TAG('C','C','H','N')}},     /* Quiotepec Chinantec -> Chinantec */
+  {"chr",      {HB_TAG('C','H','R',' ')}},     /* Cherokee */
+  {"chy",      {HB_TAG('C','H','Y',' ')}},     /* Cheyenne */
+  {"chz",      {HB_TAG('C','C','H','N')}},     /* Ozumacín Chinantec -> Chinantec */
+  {"ciw",      {HB_TAG('O','J','B',' ')}},     /* Chippewa -> Ojibway */
+  {"cja",      {HB_TAG('C','J','A',' ')}},     /* Western Cham */
+  {"cjm",      {HB_TAG('C','J','M',' ')}},     /* Eastern Cham */
+  {"cjy",      {HB_TAG('Z','H','S',' ')}},     /* Jinyu Chinese -> Chinese Simplified */
+  {"cka",      {HB_TAG('Q','I','N',' ')}},     /* Khumi Awa Chin (retired code) -> Chin */
+  {"ckb",      {HB_TAG('K','U','R',' ')}},     /* Central Kurdish -> Kurdish */
+  {"ckt",      {HB_TAG('C','H','K',' ')}},     /* Chukot -> Chukchi */
+  {"clc",      {HB_TAG('A','T','H',' ')}},     /* Chilcotin -> Athapaskan */
+  {"cld",      {HB_TAG('S','Y','R',' ')}},     /* Chaldean Neo-Aramaic -> Syriac */
+  {"cle",      {HB_TAG('C','C','H','N')}},     /* Lealao Chinantec -> Chinantec */
+  {"cmn",      {HB_TAG('Z','H','S',' ')}},     /* Mandarin Chinese -> Chinese Simplified */
+  {"cmr",      {HB_TAG('Q','I','N',' ')}},     /* Mro-Khimi Chin -> Chin */
+  {"cnb",      {HB_TAG('Q','I','N',' ')}},     /* Chinbon Chin -> Chin */
+  {"cnh",      {HB_TAG('Q','I','N',' ')}},     /* Hakha Chin -> Chin */
+  {"cnk",      {HB_TAG('Q','I','N',' ')}},     /* Khumi Chin -> Chin */
+  {"cnl",      {HB_TAG('C','C','H','N')}},     /* Lalana Chinantec -> Chinantec */
+  {"cnt",      {HB_TAG('C','C','H','N')}},     /* Tepetotutla Chinantec -> Chinantec */
+  {"cnw",      {HB_TAG('Q','I','N',' ')}},     /* Ngawn Chin -> Chin */
+  {"co",       {HB_TAG('C','O','S',' ')}},     /* Corsican */
+  {"coa",      {HB_TAG('M','L','Y',' ')}},     /* Cocos Islands Malay -> Malay */
+  {"cop",      {HB_TAG('C','O','P',' ')}},     /* Coptic */
+  {"coq",      {HB_TAG('A','T','H',' ')}},     /* Coquille -> Athapaskan */
+  {"cpa",      {HB_TAG('C','C','H','N')}},     /* Palantla Chinantec -> Chinantec */
+  {"cpe",      {HB_TAG('C','P','P',' ')}},     /* English-based creoles and pidgins [family] -> Creoles */
+  {"cpf",      {HB_TAG('C','P','P',' ')}},     /* French-based creoles and pidgins [family] -> Creoles */
+  {"cpp",      {HB_TAG('C','P','P',' ')}},     /* Portuguese-based creoles and pidgins [family] -> Creoles */
+  {"cpx",      {HB_TAG('Z','H','S',' ')}},     /* Pu-Xian Chinese -> Chinese Simplified */
+  {"cqd",      {HB_TAG('H','M','N',' ')}},     /* Chuanqiandian Cluster Miao -> Hmong */
+  {"cqu",      {HB_TAG('Q','U','H',' ')}},     /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+  {"cr",       {HB_TAG('C','R','E',' '),       /* Cree [macrolanguage] */
+                HB_TAG('Y','C','R',' ')}},     /* Cree [macrolanguage] -> Y-Cree */
+  {"crh",      {HB_TAG('C','R','T',' ')}},     /* Crimean Tatar */
+  {"crj",      {HB_TAG('E','C','R',' ')}},     /* Southern East Cree -> Eastern Cree */
+  {"crk",      {HB_TAG('W','C','R',' ')}},     /* Plains Cree -> West-Cree */
+  {"crl",      {HB_TAG('E','C','R',' ')}},     /* Northern East Cree -> Eastern Cree */
+  {"crm",      {HB_TAG('M','C','R',' '),       /* Moose Cree */
+                HB_TAG('L','C','R',' ')}},     /* Moose Cree -> L-Cree */
+  {"crp",      {HB_TAG('C','P','P',' ')}},     /* Creoles and pidgins [family] -> Creoles */
+  {"crx",      {HB_TAG('C','R','R',' '),       /* Carrier */
+                HB_TAG('A','T','H',' ')}},     /* Carrier -> Athapaskan */
+  {"cs",       {HB_TAG('C','S','Y',' ')}},     /* Czech */
+  {"csa",      {HB_TAG('C','C','H','N')}},     /* Chiltepec Chinantec -> Chinantec */
+  {"csb",      {HB_TAG('C','S','B',' ')}},     /* Kashubian */
+  {"csh",      {HB_TAG('Q','I','N',' ')}},     /* Asho Chin -> Chin */
+  {"cso",      {HB_TAG('C','C','H','N')}},     /* Sochiapam Chinantec -> Chinantec */
+  {"csw",      {HB_TAG('N','C','R',' '),       /* Swampy Cree -> N-Cree */
+                HB_TAG('N','H','C',' ')}},     /* Swampy Cree -> Norway House Cree */
+  {"csy",      {HB_TAG('Q','I','N',' ')}},     /* Siyin Chin -> Chin */
+  {"ctc",      {HB_TAG('A','T','H',' ')}},     /* Chetco -> Athapaskan */
+  {"ctd",      {HB_TAG('Q','I','N',' ')}},     /* Tedim Chin -> Chin */
+  {"cte",      {HB_TAG('C','C','H','N')}},     /* Tepinapa Chinantec -> Chinantec */
+  {"ctg",      {HB_TAG('C','T','G',' ')}},     /* Chittagonian */
+  {"ctl",      {HB_TAG('C','C','H','N')}},     /* Tlacoatzintepec Chinantec -> Chinantec */
+  {"cts",      {HB_TAG('B','I','K',' ')}},     /* Northern Catanduanes Bikol -> Bikol */
+  {"cu",       {HB_TAG('C','S','L',' ')}},     /* Church Slavonic */
+  {"cuc",      {HB_TAG('C','C','H','N')}},     /* Usila Chinantec -> Chinantec */
+  {"cuk",      {HB_TAG('C','U','K',' ')}},     /* San Blas Kuna */
+  {"cv",       {HB_TAG('C','H','U',' ')}},     /* Chuvash */
+  {"cvn",      {HB_TAG('C','C','H','N')}},     /* Valle Nacional Chinantec -> Chinantec */
+  {"cwd",      {HB_TAG('D','C','R',' '),       /* Woods Cree */
+                HB_TAG('T','C','R',' ')}},     /* Woods Cree -> TH-Cree */
+  {"cy",       {HB_TAG('W','E','L',' ')}},     /* Welsh */
+  {"czh",      {HB_TAG('Z','H','S',' ')}},     /* Huizhou Chinese -> Chinese Simplified */
+  {"czo",      {HB_TAG('Z','H','S',' ')}},     /* Min Zhong Chinese -> Chinese Simplified */
+  {"czt",      {HB_TAG('Q','I','N',' ')}},     /* Zotung Chin -> Chin */
+  {"da",       {HB_TAG('D','A','N',' ')}},     /* Danish */
+  {"dao",      {HB_TAG('Q','I','N',' ')}},     /* Daai Chin -> Chin */
+  {"dap",      {HB_TAG('N','I','S',' ')}},     /* Nisi (India) (retired code) */
+  {"dar",      {HB_TAG('D','A','R',' ')}},     /* Dargwa */
+  {"dax",      {HB_TAG('D','A','X',' ')}},     /* Dayi */
+  {"de",       {HB_TAG('D','E','U',' ')}},     /* German */
+  {"den",      {HB_TAG('S','L','A',' '),       /* Slave (Athapascan) [macrolanguage] -> Slavey */
+                HB_TAG('A','T','H',' ')}},     /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+  {"dgo",      {HB_TAG('D','G','O',' ')}},     /* Dogri */
+  {"dgr",      {HB_TAG('A','T','H',' ')}},     /* Dogrib -> Athapaskan */
+  {"dhd",      {HB_TAG('M','A','W',' ')}},     /* Dhundari -> Marwari */
+  {"dhg",      {HB_TAG('D','H','G',' ')}},     /* Dhangu */
+  {"dib",      {HB_TAG('D','N','K',' ')}},     /* South Central Dinka -> Dinka */
+  {"dik",      {HB_TAG('D','N','K',' ')}},     /* Southwestern Dinka -> Dinka */
+  {"din",      {HB_TAG('D','N','K',' ')}},     /* Dinka [macrolanguage] */
+  {"dip",      {HB_TAG('D','N','K',' ')}},     /* Northeastern Dinka -> Dinka */
+  {"diq",      {HB_TAG('D','I','Q',' ')}},     /* Dimli */
+  {"diw",      {HB_TAG('D','N','K',' ')}},     /* Northwestern Dinka -> Dinka */
+  {"dje",      {HB_TAG('D','J','R',' ')}},     /* Zarma */
+  {"djr",      {HB_TAG('D','J','R','0')}},     /* Djambarrpuyngu */
+  {"dks",      {HB_TAG('D','N','K',' ')}},     /* Southeastern Dinka -> Dinka */
+  {"dng",      {HB_TAG('D','U','N',' ')}},     /* Dungan */
+  {"dnj",      {HB_TAG('D','N','J',' ')}},     /* Dan */
+  {"doi",      {HB_TAG('D','G','R',' ')}},     /* Dogri [macrolanguage] */
+  {"drh",      {HB_TAG('M','N','G',' ')}},     /* Darkhat (retired code) -> Mongolian */
+  {"drw",      {HB_TAG('D','R','I',' ')}},     /* Darwazi (retired code) -> Dari */
+  {"dsb",      {HB_TAG('L','S','B',' ')}},     /* Lower Sorbian */
+  {"dty",      {HB_TAG('N','E','P',' ')}},     /* Dotyali -> Nepali */
+  {"duj",      {HB_TAG('D','U','J',' ')}},     /* Dhuwal (retired code) */
+  {"dup",      {HB_TAG('M','L','Y',' ')}},     /* Duano -> Malay */
+  {"dv",       {HB_TAG('D','I','V',' '),       /* Divehi (Dhivehi, Maldivian) */
+                HB_TAG('D','H','V',' ')}},     /* Divehi (Dhivehi, Maldivian) (deprecated) */
+  {"dwu",      {HB_TAG('D','U','J',' ')}},     /* Dhuwal */
+  {"dwy",      {HB_TAG('D','U','J',' ')}},     /* Dhuwaya -> Dhuwal */
+  {"dyu",      {HB_TAG('J','U','L',' ')}},     /* Dyula -> Jula */
+  {"dz",       {HB_TAG('D','Z','N',' ')}},     /* Dzongkha */
+  {"ee",       {HB_TAG('E','W','E',' ')}},     /* Ewe */
+  {"efi",      {HB_TAG('E','F','I',' ')}},     /* Efik */
+  {"ekk",      {HB_TAG('E','T','I',' ')}},     /* Standard Estonian -> Estonian */
+  {"el",       {HB_TAG('E','L','L',' ')}},     /* Modern Greek (1453-) -> Greek */
+  {"emk",      {HB_TAG('E','M','K',' '),       /* Eastern Maninkakan */
+                HB_TAG('M','N','K',' ')}},     /* Eastern Maninkakan -> Maninka */
+  {"en",       {HB_TAG('E','N','G',' ')}},     /* English */
+  {"enb",      {HB_TAG('K','A','L',' ')}},     /* Markweeta -> Kalenjin */
+  {"enf",      {HB_TAG('F','N','E',' ')}},     /* Forest Enets -> Forest Nenets */
+  {"enh",      {HB_TAG('T','N','E',' ')}},     /* Tundra Enets -> Tundra Nenets */
+  {"eo",       {HB_TAG('N','T','O',' ')}},     /* Esperanto */
+  {"es",       {HB_TAG('E','S','P',' ')}},     /* Spanish */
+  {"esg",      {HB_TAG('G','O','N',' ')}},     /* Aheri Gondi -> Gondi */
+  {"esi",      {HB_TAG('I','P','K',' ')}},     /* North Alaskan Inupiatun -> Inupiat */
+  {"esk",      {HB_TAG('I','P','K',' ')}},     /* Northwest Alaska Inupiatun -> Inupiat */
+  {"esu",      {HB_TAG('E','S','U',' ')}},     /* Central Yupik */
+  {"et",       {HB_TAG('E','T','I',' ')}},     /* Estonian [macrolanguage] */
+  {"eto",      {HB_TAG('B','T','I',' ')}},     /* Eton (Cameroon) -> Beti */
+  {"eu",       {HB_TAG('E','U','Q',' ')}},     /* Basque */
+  {"eve",      {HB_TAG('E','V','N',' ')}},     /* Even */
+  {"evn",      {HB_TAG('E','V','K',' ')}},     /* Evenki */
+  {"ewo",      {HB_TAG('B','T','I',' ')}},     /* Ewondo -> Beti */
+  {"eyo",      {HB_TAG('K','A','L',' ')}},     /* Keiyo -> Kalenjin */
+  {"fa",       {HB_TAG('F','A','R',' ')}},     /* Persian [macrolanguage] */
+  {"fan",      {HB_TAG('F','A','N','0')}},     /* Fang (Equatorial Guinea) */
+  {"fat",      {HB_TAG('F','A','T',' ')}},     /* Fanti */
+  {"fbl",      {HB_TAG('B','I','K',' ')}},     /* West Albay Bikol -> Bikol */
+  {"ff",       {HB_TAG('F','U','L',' ')}},     /* Fulah [macrolanguage] */
+  {"ffm",      {HB_TAG('F','U','L',' ')}},     /* Maasina Fulfulde -> Fulah */
+  {"fi",       {HB_TAG('F','I','N',' ')}},     /* Finnish */
+  {"fil",      {HB_TAG('P','I','L',' ')}},     /* Filipino */
+  {"fj",       {HB_TAG('F','J','I',' ')}},     /* Fijian */
+  {"flm",      {HB_TAG('H','A','L',' '),       /* Halam (Falam Chin) (retired code) */
+                HB_TAG('Q','I','N',' ')}},     /* Falam Chin (retired code) -> Chin */
+  {"fmp",      {HB_TAG('F','M','P',' ')}},     /* Fe'fe' */
+  {"fo",       {HB_TAG('F','O','S',' ')}},     /* Faroese */
+  {"fon",      {HB_TAG('F','O','N',' ')}},     /* Fon */
+  {"fr",       {HB_TAG('F','R','A',' ')}},     /* French */
+  {"frc",      {HB_TAG('F','R','C',' ')}},     /* Cajun French */
+  {"frp",      {HB_TAG('F','R','P',' ')}},     /* Arpitan */
+  {"fub",      {HB_TAG('F','U','L',' ')}},     /* Adamawa Fulfulde -> Fulah */
+  {"fuc",      {HB_TAG('F','U','L',' ')}},     /* Pulaar -> Fulah */
+  {"fue",      {HB_TAG('F','U','L',' ')}},     /* Borgu Fulfulde -> Fulah */
+  {"fuf",      {HB_TAG('F','T','A',' ')}},     /* Pular -> Futa */
+  {"fuh",      {HB_TAG('F','U','L',' ')}},     /* Western Niger Fulfulde -> Fulah */
+  {"fui",      {HB_TAG('F','U','L',' ')}},     /* Bagirmi Fulfulde -> Fulah */
+  {"fuq",      {HB_TAG('F','U','L',' ')}},     /* Central-Eastern Niger Fulfulde -> Fulah */
+  {"fur",      {HB_TAG('F','R','L',' ')}},     /* Friulian */
+  {"fuv",      {HB_TAG('F','U','V',' ')}},     /* Nigerian Fulfulde */
+  {"fy",       {HB_TAG('F','R','I',' ')}},     /* Western Frisian -> Frisian */
+  {"ga",       {HB_TAG('I','R','I',' ')}},     /* Irish */
+  {"gaa",      {HB_TAG('G','A','D',' ')}},     /* Ga */
+  {"gag",      {HB_TAG('G','A','G',' ')}},     /* Gagauz */
+  {"gan",      {HB_TAG('Z','H','S',' ')}},     /* Gan Chinese -> Chinese Simplified */
+  {"gax",      {HB_TAG('O','R','O',' ')}},     /* Borana-Arsi-Guji Oromo -> Oromo */
+  {"gaz",      {HB_TAG('O','R','O',' ')}},     /* West Central Oromo -> Oromo */
+  {"gbm",      {HB_TAG('G','A','W',' ')}},     /* Garhwali */
+  {"gce",      {HB_TAG('A','T','H',' ')}},     /* Galice -> Athapaskan */
+  {"gd",       {HB_TAG('G','A','E',' ')}},     /* Scottish Gaelic (Gaelic) */
+  {"gda",      {HB_TAG('R','A','J',' ')}},     /* Gade Lohar -> Rajasthani */
+  {"gez",      {HB_TAG('G','E','Z',' ')}},     /* Geez */
+  {"ggo",      {HB_TAG('G','O','N',' ')}},     /* Southern Gondi (retired code) -> Gondi */
+  {"gih",      {HB_TAG('G','I','H',' ')}},     /* Githabul */
+  {"gil",      {HB_TAG('G','I','L','0')}},     /* Kiribati (Gilbertese) */
+  {"gju",      {HB_TAG('R','A','J',' ')}},     /* Gujari -> Rajasthani */
+  {"gkp",      {HB_TAG('G','K','P',' ')}},     /* Guinea Kpelle -> Kpelle (Guinea) */
+  {"gl",       {HB_TAG('G','A','L',' ')}},     /* Galician */
+  {"gld",      {HB_TAG('N','A','N',' ')}},     /* Nanai */
+  {"glk",      {HB_TAG('G','L','K',' ')}},     /* Gilaki */
+  {"gn",       {HB_TAG('G','U','A',' ')}},     /* Guarani [macrolanguage] */
+  {"gnn",      {HB_TAG('G','N','N',' ')}},     /* Gumatj */
+  {"gno",      {HB_TAG('G','O','N',' ')}},     /* Northern Gondi -> Gondi */
+  {"gnw",      {HB_TAG('G','U','A',' ')}},     /* Western Bolivian Guaraní -> Guarani */
+  {"gog",      {HB_TAG('G','O','G',' ')}},     /* Gogo */
+  {"gom",      {HB_TAG('K','O','K',' ')}},     /* Goan Konkani -> Konkani */
+  {"gon",      {HB_TAG('G','O','N',' ')}},     /* Gondi [macrolanguage] */
+  {"grt",      {HB_TAG('G','R','O',' ')}},     /* Garo */
+  {"gru",      {HB_TAG('S','O','G',' ')}},     /* Kistane -> Sodo Gurage */
+  {"gsw",      {HB_TAG('A','L','S',' ')}},     /* Alsatian */
+  {"gu",       {HB_TAG('G','U','J',' ')}},     /* Gujarati */
+  {"guc",      {HB_TAG('G','U','C',' ')}},     /* Wayuu */
+  {"guf",      {HB_TAG('G','U','F',' ')}},     /* Gupapuyngu */
+  {"gug",      {HB_TAG('G','U','A',' ')}},     /* Paraguayan Guaraní -> Guarani */
+  {"gui",      {HB_TAG('G','U','A',' ')}},     /* Eastern Bolivian Guaraní -> Guarani */
+  {"guk",      {HB_TAG('G','M','Z',' '),       /* Gumuz */
+                HB_TAG('G','U','K',' ')}},     /* Gumuz (SIL fonts) */
+  {"gun",      {HB_TAG('G','U','A',' ')}},     /* Mbyá Guaraní -> Guarani */
+  {"guz",      {HB_TAG('G','U','Z',' ')}},     /* Gusii */
+  {"gv",       {HB_TAG('M','N','X',' ')}},     /* Manx */
+  {"gwi",      {HB_TAG('A','T','H',' ')}},     /* Gwichʼin -> Athapaskan */
+  {"ha",       {HB_TAG('H','A','U',' ')}},     /* Hausa */
+  {"haa",      {HB_TAG('A','T','H',' ')}},     /* Han -> Athapaskan */
+  {"hae",      {HB_TAG('O','R','O',' ')}},     /* Eastern Oromo -> Oromo */
+  {"hak",      {HB_TAG('Z','H','S',' ')}},     /* Hakka Chinese -> Chinese Simplified */
+  {"har",      {HB_TAG('H','R','I',' ')}},     /* Harari */
+  {"haw",      {HB_TAG('H','A','W',' ')}},     /* Hawaiian */
+  {"hay",      {HB_TAG('H','A','Y',' ')}},     /* Haya */
+  {"haz",      {HB_TAG('H','A','Z',' ')}},     /* Hazaragi */
+  {"he",       {HB_TAG('I','W','R',' ')}},     /* Hebrew */
+  {"hea",      {HB_TAG('H','M','N',' ')}},     /* Northern Qiandong Miao -> Hmong */
+  {"hi",       {HB_TAG('H','I','N',' ')}},     /* Hindi */
+  {"hil",      {HB_TAG('H','I','L',' ')}},     /* Hiligaynon */
+  {"hji",      {HB_TAG('M','L','Y',' ')}},     /* Haji -> Malay */
+  {"hlt",      {HB_TAG('Q','I','N',' ')}},     /* Matu Chin -> Chin */
+  {"hma",      {HB_TAG('H','M','N',' ')}},     /* Southern Mashan Hmong -> Hmong */
+  {"hmc",      {HB_TAG('H','M','N',' ')}},     /* Central Huishui Hmong -> Hmong */
+  {"hmd",      {HB_TAG('H','M','N',' ')}},     /* Large Flowery Miao -> Hmong */
+  {"hme",      {HB_TAG('H','M','N',' ')}},     /* Eastern Huishui Hmong -> Hmong */
+  {"hmg",      {HB_TAG('H','M','N',' ')}},     /* Southwestern Guiyang Hmong -> Hmong */
+  {"hmh",      {HB_TAG('H','M','N',' ')}},     /* Southwestern Huishui Hmong -> Hmong */
+  {"hmi",      {HB_TAG('H','M','N',' ')}},     /* Northern Huishui Hmong -> Hmong */
+  {"hmj",      {HB_TAG('H','M','N',' ')}},     /* Ge -> Hmong */
+  {"hml",      {HB_TAG('H','M','N',' ')}},     /* Luopohe Hmong -> Hmong */
+  {"hmm",      {HB_TAG('H','M','N',' ')}},     /* Central Mashan Hmong -> Hmong */
+  {"hmn",      {HB_TAG('H','M','N',' ')}},     /* Hmong [macrolanguage] */
+  {"hmp",      {HB_TAG('H','M','N',' ')}},     /* Northern Mashan Hmong -> Hmong */
+  {"hmq",      {HB_TAG('H','M','N',' ')}},     /* Eastern Qiandong Miao -> Hmong */
+  {"hms",      {HB_TAG('H','M','N',' ')}},     /* Southern Qiandong Miao -> Hmong */
+  {"hmw",      {HB_TAG('H','M','N',' ')}},     /* Western Mashan Hmong -> Hmong */
+  {"hmy",      {HB_TAG('H','M','N',' ')}},     /* Southern Guiyang Hmong -> Hmong */
+  {"hmz",      {HB_TAG('H','M','N',' ')}},     /* Hmong Shua -> Hmong */
+  {"hnd",      {HB_TAG('H','N','D',' ')}},     /* Southern Hindko -> Hindko */
+  {"hne",      {HB_TAG('C','H','H',' ')}},     /* Chhattisgarhi -> Chattisgarhi */
+  {"hnj",      {HB_TAG('H','M','N',' ')}},     /* Hmong Njua -> Hmong */
+  {"hno",      {HB_TAG('H','N','D',' ')}},     /* Northern Hindko -> Hindko */
+  {"ho",       {HB_TAG('H','M','O',' ')}},     /* Hiri Motu */
+  {"hoc",      {HB_TAG('H','O',' ',' ')}},     /* Ho */
+  {"hoi",      {HB_TAG('A','T','H',' ')}},     /* Holikachuk -> Athapaskan */
+  {"hoj",      {HB_TAG('H','A','R',' ')}},     /* Hadothi -> Harauti */
+  {"hr",       {HB_TAG('H','R','V',' ')}},     /* Croatian */
+  {"hrm",      {HB_TAG('H','M','N',' ')}},     /* Horned Miao -> Hmong */
+  {"hsb",      {HB_TAG('U','S','B',' ')}},     /* Upper Sorbian */
+  {"hsn",      {HB_TAG('Z','H','S',' ')}},     /* Xiang Chinese -> Chinese Simplified */
+  {"ht",       {HB_TAG('H','A','I',' ')}},     /* Haitian (Haitian Creole) */
+  {"hu",       {HB_TAG('H','U','N',' ')}},     /* Hungarian */
+  {"huj",      {HB_TAG('H','M','N',' ')}},     /* Northern Guiyang Hmong -> Hmong */
+  {"hup",      {HB_TAG('A','T','H',' ')}},     /* Hupa -> Athapaskan */
+  {"hy",       {HB_TAG('H','Y','E','0'),       /* Armenian -> Armenian East */
+                HB_TAG('H','Y','E',' ')}},     /* Armenian */
+  {"hyw",      {HB_TAG('H','Y','E',' ')}},     /* Western Armenian -> Armenian */
+  {"hz",       {HB_TAG('H','E','R',' ')}},     /* Herero */
+  {"ia",       {HB_TAG('I','N','A',' ')}},     /* Interlingua (International Auxiliary Language Association) */
+  {"iba",      {HB_TAG('I','B','A',' ')}},     /* Iban */
+  {"ibb",      {HB_TAG('I','B','B',' ')}},     /* Ibibio */
+  {"id",       {HB_TAG('I','N','D',' ')}},     /* Indonesian */
+  {"ida",      {HB_TAG('L','U','H',' ')}},     /* Idakho-Isukha-Tiriki -> Luyia */
+  {"ie",       {HB_TAG('I','L','E',' ')}},     /* Interlingue */
+  {"ig",       {HB_TAG('I','B','O',' ')}},     /* Igbo */
+  {"igb",      {HB_TAG('E','B','I',' ')}},     /* Ebira */
+  {"ii",       {HB_TAG('Y','I','M',' ')}},     /* Sichuan Yi -> Yi Modern */
+  {"ijc",      {HB_TAG('I','J','O',' ')}},     /* Izon -> Ijo */
+  {"ijo",      {HB_TAG('I','J','O',' ')}},     /* Ijo [family] */
+  {"ik",       {HB_TAG('I','P','K',' ')}},     /* Inupiaq [macrolanguage] -> Inupiat */
+  {"ike",      {HB_TAG('I','N','U',' ')}},     /* Eastern Canadian Inuktitut -> Inuktitut */
+  {"ikt",      {HB_TAG('I','N','U',' ')}},     /* Inuinnaqtun -> Inuktitut */
+  {"ilo",      {HB_TAG('I','L','O',' ')}},     /* Iloko -> Ilokano */
+  {"in",       {HB_TAG('I','N','D',' ')}},     /* Indonesian (retired code) */
+  {"ing",      {HB_TAG('A','T','H',' ')}},     /* Degexit'an -> Athapaskan */
+  {"inh",      {HB_TAG('I','N','G',' ')}},     /* Ingush */
+  {"io",       {HB_TAG('I','D','O',' ')}},     /* Ido */
+  {"is",       {HB_TAG('I','S','L',' ')}},     /* Icelandic */
+  {"it",       {HB_TAG('I','T','A',' ')}},     /* Italian */
+  {"iu",       {HB_TAG('I','N','U',' ')}},     /* Inuktitut [macrolanguage] */
+  {"iw",       {HB_TAG('I','W','R',' ')}},     /* Hebrew (retired code) */
+  {"ja",       {HB_TAG('J','A','N',' ')}},     /* Japanese */
+  {"jak",      {HB_TAG('M','L','Y',' ')}},     /* Jakun -> Malay */
+  {"jam",      {HB_TAG('J','A','M',' ')}},     /* Jamaican Creole English -> Jamaican Creole */
+  {"jax",      {HB_TAG('M','L','Y',' ')}},     /* Jambi Malay -> Malay */
+  {"jbo",      {HB_TAG('J','B','O',' ')}},     /* Lojban */
+  {"jct",      {HB_TAG('J','C','T',' ')}},     /* Krymchak */
+  {"ji",       {HB_TAG('J','I','I',' ')}},     /* Yiddish (retired code) */
+  {"jv",       {HB_TAG('J','A','V',' ')}},     /* Javanese */
+  {"jw",       {HB_TAG('J','A','V',' ')}},     /* Javanese (retired code) */
+  {"ka",       {HB_TAG('K','A','T',' ')}},     /* Georgian */
+  {"kaa",      {HB_TAG('K','R','K',' ')}},     /* Kara-Kalpak -> Karakalpak */
+  {"kab",      {HB_TAG('K','A','B','0')}},     /* Kabyle */
+  {"kam",      {HB_TAG('K','M','B',' ')}},     /* Kamba (Kenya) */
+  {"kar",      {HB_TAG('K','R','N',' ')}},     /* Karen [family] */
+  {"kbd",      {HB_TAG('K','A','B',' ')}},     /* Kabardian */
+  {"kby",      {HB_TAG('K','N','R',' ')}},     /* Manga Kanuri -> Kanuri */
+  {"kca",      {HB_TAG('K','H','K',' '),       /* Khanty -> Khanty-Kazim */
+                HB_TAG('K','H','S',' '),       /* Khanty -> Khanty-Shurishkar */
+                HB_TAG('K','H','V',' ')}},     /* Khanty -> Khanty-Vakhi */
+  {"kde",      {HB_TAG('K','D','E',' ')}},     /* Makonde */
+  {"kdr",      {HB_TAG('K','R','M',' ')}},     /* Karaim */
+  {"kdt",      {HB_TAG('K','U','Y',' ')}},     /* Kuy */
+  {"kea",      {HB_TAG('K','E','A',' ')}},     /* Kabuverdianu (Crioulo) */
+  {"kek",      {HB_TAG('K','E','K',' ')}},     /* Kekchi */
+  {"kex",      {HB_TAG('K','K','N',' ')}},     /* Kukna -> Kokni */
+  {"kfa",      {HB_TAG('K','O','D',' ')}},     /* Kodava -> Kodagu */
+  {"kfr",      {HB_TAG('K','A','C',' ')}},     /* Kachhi -> Kachchi */
+  {"kfx",      {HB_TAG('K','U','L',' ')}},     /* Kullu Pahari -> Kulvi */
+  {"kfy",      {HB_TAG('K','M','N',' ')}},     /* Kumaoni */
+  {"kg",       {HB_TAG('K','O','N','0')}},     /* Kongo [macrolanguage] */
+  {"kha",      {HB_TAG('K','S','I',' ')}},     /* Khasi */
+  {"khb",      {HB_TAG('X','B','D',' ')}},     /* Lü */
+  {"khk",      {HB_TAG('M','N','G',' ')}},     /* Halh Mongolian -> Mongolian */
+  {"kht",      {HB_TAG('K','H','N',' '),       /* Khamti -> Khamti Shan (Microsoft fonts) */
+                HB_TAG('K','H','T',' ')}},     /* Khamti -> Khamti Shan (OpenType spec and SIL fonts) */
+  {"khw",      {HB_TAG('K','H','W',' ')}},     /* Khowar */
+  {"ki",       {HB_TAG('K','I','K',' ')}},     /* Kikuyu (Gikuyu) */
+  {"kiu",      {HB_TAG('K','I','U',' ')}},     /* Kirmanjki */
+  {"kj",       {HB_TAG('K','U','A',' ')}},     /* Kuanyama */
+  {"kjd",      {HB_TAG('K','J','D',' ')}},     /* Southern Kiwai */
+  {"kjh",      {HB_TAG('K','H','A',' ')}},     /* Khakas -> Khakass */
+  {"kjp",      {HB_TAG('K','J','P',' ')}},     /* Pwo Eastern Karen -> Eastern Pwo Karen */
+  {"kjz",      {HB_TAG('K','J','Z',' ')}},     /* Bumthangkha */
+  {"kk",       {HB_TAG('K','A','Z',' ')}},     /* Kazakh */
+  {"kkz",      {HB_TAG('A','T','H',' ')}},     /* Kaska -> Athapaskan */
+  {"kl",       {HB_TAG('G','R','N',' ')}},     /* Greenlandic */
+  {"kln",      {HB_TAG('K','A','L',' ')}},     /* Kalenjin [macrolanguage] */
+  {"km",       {HB_TAG('K','H','M',' ')}},     /* Khmer */
+  {"kmb",      {HB_TAG('M','B','N',' ')}},     /* Kimbundu -> Mbundu */
+  {"kmr",      {HB_TAG('K','U','R',' ')}},     /* Northern Kurdish -> Kurdish */
+  {"kmw",      {HB_TAG('K','M','O',' ')}},     /* Komo (Democratic Republic of Congo) */
+  {"kmz",      {HB_TAG('K','M','Z',' ')}},     /* Khorasani Turkish -> Khorasani Turkic */
+  {"kn",       {HB_TAG('K','A','N',' ')}},     /* Kannada */
+  {"knc",      {HB_TAG('K','N','R',' ')}},     /* Central Kanuri -> Kanuri */
+  {"kng",      {HB_TAG('K','O','N','0')}},     /* Koongo -> Kongo */
+  {"knn",      {HB_TAG('K','O','K',' ')}},     /* Konkani */
+  {"ko",       {HB_TAG('K','O','R',' ')}},     /* Korean */
+  {"koi",      {HB_TAG('K','O','P',' ')}},     /* Komi-Permyak */
+  {"kok",      {HB_TAG('K','O','K',' ')}},     /* Konkani [macrolanguage] */
+  {"kos",      {HB_TAG('K','O','S',' ')}},     /* Kosraean */
+  {"koy",      {HB_TAG('A','T','H',' ')}},     /* Koyukon -> Athapaskan */
+  {"kpe",      {HB_TAG('K','P','L',' ')}},     /* Kpelle [macrolanguage] */
+  {"kpv",      {HB_TAG('K','O','Z',' ')}},     /* Komi-Zyrian */
+  {"kpy",      {HB_TAG('K','Y','K',' ')}},     /* Koryak */
+  {"kqs",      {HB_TAG('K','I','S',' ')}},     /* Northern Kissi -> Kisii */
+  {"kqy",      {HB_TAG('K','R','T',' ')}},     /* Koorete */
+  {"kr",       {HB_TAG('K','N','R',' ')}},     /* Kanuri [macrolanguage] */
+  {"krc",      {HB_TAG('K','A','R',' '),       /* Karachay-Balkar -> Karachay */
+                HB_TAG('B','A','L',' ')}},     /* Karachay-Balkar -> Balkar */
+  {"kri",      {HB_TAG('K','R','I',' ')}},     /* Krio */
+  {"krl",      {HB_TAG('K','R','L',' ')}},     /* Karelian */
+  {"krt",      {HB_TAG('K','N','R',' ')}},     /* Tumari Kanuri -> Kanuri */
+  {"kru",      {HB_TAG('K','U','U',' ')}},     /* Kurukh */
+  {"ks",       {HB_TAG('K','S','H',' ')}},     /* Kashmiri */
+  {"ksh",      {HB_TAG('K','S','H','0')}},     /* Kölsch -> Ripuarian */
+  {"kss",      {HB_TAG('K','I','S',' ')}},     /* Southern Kisi -> Kisii */
+  {"ksw",      {HB_TAG('K','S','W',' ')}},     /* S’gaw Karen */
+  {"ktb",      {HB_TAG('K','E','B',' ')}},     /* Kambaata -> Kebena */
+  {"ktu",      {HB_TAG('K','O','N',' ')}},     /* Kituba (Democratic Republic of Congo) -> Kikongo */
+  {"ktw",      {HB_TAG('A','T','H',' ')}},     /* Kato -> Athapaskan */
+  {"ku",       {HB_TAG('K','U','R',' ')}},     /* Kurdish [macrolanguage] */
+  {"kum",      {HB_TAG('K','U','M',' ')}},     /* Kumyk */
+  {"kuu",      {HB_TAG('A','T','H',' ')}},     /* Upper Kuskokwim -> Athapaskan */
+  {"kv",       {HB_TAG('K','O','M',' ')}},     /* Komi [macrolanguage] */
+  {"kvb",      {HB_TAG('M','L','Y',' ')}},     /* Kubu -> Malay */
+  {"kvr",      {HB_TAG('M','L','Y',' ')}},     /* Kerinci -> Malay */
+  {"kw",       {HB_TAG('C','O','R',' ')}},     /* Cornish */
+  {"kwy",      {HB_TAG('K','O','N','0')}},     /* San Salvador Kongo -> Kongo */
+  {"kxc",      {HB_TAG('K','M','S',' ')}},     /* Konso -> Komso */
+  {"kxd",      {HB_TAG('M','L','Y',' ')}},     /* Brunei -> Malay */
+  {"kxu",      {HB_TAG('K','U','I',' ')}},     /* Kui (India) */
+  {"ky",       {HB_TAG('K','I','R',' ')}},     /* Kirghiz (Kyrgyz) */
+  {"kyu",      {HB_TAG('K','Y','U',' ')}},     /* Western Kayah */
+  {"la",       {HB_TAG('L','A','T',' ')}},     /* Latin */
+  {"lad",      {HB_TAG('J','U','D',' ')}},     /* Ladino */
+  {"lb",       {HB_TAG('L','T','Z',' ')}},     /* Luxembourgish */
+  {"lbe",      {HB_TAG('L','A','K',' ')}},     /* Lak */
+  {"lbj",      {HB_TAG('L','D','K',' ')}},     /* Ladakhi */
+  {"lbl",      {HB_TAG('B','I','K',' ')}},     /* Libon Bikol -> Bikol */
+  {"lce",      {HB_TAG('M','L','Y',' ')}},     /* Loncong -> Malay */
+  {"lcf",      {HB_TAG('M','L','Y',' ')}},     /* Lubu -> Malay */
+  {"ldi",      {HB_TAG('K','O','N','0')}},     /* Laari -> Kongo */
+  {"lez",      {HB_TAG('L','E','Z',' ')}},     /* Lezghian -> Lezgi */
+  {"lg",       {HB_TAG('L','U','G',' ')}},     /* Ganda */
+  {"li",       {HB_TAG('L','I','M',' ')}},     /* Limburgish */
+  {"lif",      {HB_TAG('L','M','B',' ')}},     /* Limbu */
+  {"lij",      {HB_TAG('L','I','J',' ')}},     /* Ligurian */
+  {"lis",      {HB_TAG('L','I','S',' ')}},     /* Lisu */
+  {"liw",      {HB_TAG('M','L','Y',' ')}},     /* Col -> Malay */
+  {"ljp",      {HB_TAG('L','J','P',' ')}},     /* Lampung Api -> Lampung */
+  {"lkb",      {HB_TAG('L','U','H',' ')}},     /* Kabras -> Luyia */
+  {"lki",      {HB_TAG('L','K','I',' ')}},     /* Laki */
+  {"lko",      {HB_TAG('L','U','H',' ')}},     /* Khayo -> Luyia */
+  {"lks",      {HB_TAG('L','U','H',' ')}},     /* Kisa -> Luyia */
+  {"lld",      {HB_TAG('L','A','D',' ')}},     /* Ladin */
+  {"lmn",      {HB_TAG('L','A','M',' ')}},     /* Lambadi -> Lambani */
+  {"lmo",      {HB_TAG('L','M','O',' ')}},     /* Lombard */
+  {"ln",       {HB_TAG('L','I','N',' ')}},     /* Lingala */
+  {"lo",       {HB_TAG('L','A','O',' ')}},     /* Lao */
+  {"lom",      {HB_TAG('L','O','M',' ')}},     /* Loma (Liberia) */
+  {"lrc",      {HB_TAG('L','R','C',' ')}},     /* Northern Luri -> Luri */
+  {"lri",      {HB_TAG('L','U','H',' ')}},     /* Marachi -> Luyia */
+  {"lrm",      {HB_TAG('L','U','H',' ')}},     /* Marama -> Luyia */
+  {"lsm",      {HB_TAG('L','U','H',' ')}},     /* Saamia -> Luyia */
+  {"lt",       {HB_TAG('L','T','H',' ')}},     /* Lithuanian */
+  {"ltg",      {HB_TAG('L','V','I',' ')}},     /* Latgalian -> Latvian */
+  {"lto",      {HB_TAG('L','U','H',' ')}},     /* Tsotso -> Luyia */
+  {"lts",      {HB_TAG('L','U','H',' ')}},     /* Tachoni -> Luyia */
+  {"lu",       {HB_TAG('L','U','B',' ')}},     /* Luba-Katanga */
+  {"lua",      {HB_TAG('L','U','A',' ')}},     /* Luba-Lulua */
+  {"luo",      {HB_TAG('L','U','O',' ')}},     /* Luo (Kenya and Tanzania) */
+  {"lus",      {HB_TAG('M','I','Z',' ')}},     /* Lushai -> Mizo */
+  {"luy",      {HB_TAG('L','U','H',' ')}},     /* Luyia [macrolanguage] */
+  {"luz",      {HB_TAG('L','R','C',' ')}},     /* Southern Luri -> Luri */
+  {"lv",       {HB_TAG('L','V','I',' ')}},     /* Latvian [macrolanguage] */
+  {"lvs",      {HB_TAG('L','V','I',' ')}},     /* Standard Latvian -> Latvian */
+  {"lwg",      {HB_TAG('L','U','H',' ')}},     /* Wanga -> Luyia */
+  {"lzh",      {HB_TAG('Z','H','T',' ')}},     /* Literary Chinese -> Chinese Traditional */
+  {"lzz",      {HB_TAG('L','A','Z',' ')}},     /* Laz */
+  {"mad",      {HB_TAG('M','A','D',' ')}},     /* Madurese -> Madura */
+  {"mag",      {HB_TAG('M','A','G',' ')}},     /* Magahi */
+  {"mai",      {HB_TAG('M','T','H',' ')}},     /* Maithili */
+  {"mak",      {HB_TAG('M','K','R',' ')}},     /* Makasar */
+  {"mam",      {HB_TAG('M','A','M',' ')}},     /* Mam */
+  {"man",      {HB_TAG('M','N','K',' ')}},     /* Mandingo [macrolanguage] -> Maninka */
+  {"max",      {HB_TAG('M','L','Y',' ')}},     /* North Moluccan Malay -> Malay */
+  {"mbo",      {HB_TAG('M','B','O',' ')}},     /* Mbo (Cameroon) */
+  {"mct",      {HB_TAG('B','T','I',' ')}},     /* Mengisa -> Beti */
+  {"mdf",      {HB_TAG('M','O','K',' ')}},     /* Moksha */
+  {"mdr",      {HB_TAG('M','D','R',' ')}},     /* Mandar */
+  {"mdy",      {HB_TAG('M','L','E',' ')}},     /* Male (Ethiopia) */
+  {"men",      {HB_TAG('M','D','E',' ')}},     /* Mende (Sierra Leone) */
+  {"meo",      {HB_TAG('M','L','Y',' ')}},     /* Kedah Malay -> Malay */
+  {"mer",      {HB_TAG('M','E','R',' ')}},     /* Meru */
+  {"mfa",      {HB_TAG('M','F','A',' ')}},     /* Pattani Malay */
+  {"mfb",      {HB_TAG('M','L','Y',' ')}},     /* Bangka -> Malay */
+  {"mfe",      {HB_TAG('M','F','E',' ')}},     /* Morisyen */
+  {"mg",       {HB_TAG('M','L','G',' ')}},     /* Malagasy [macrolanguage] */
+  {"mh",       {HB_TAG('M','A','H',' ')}},     /* Marshallese */
+  {"mhr",      {HB_TAG('L','M','A',' ')}},     /* Eastern Mari -> Low Mari */
+  {"mhv",      {HB_TAG('A','R','K',' ')}},     /* Arakanese (retired code) -> Rakhine */
+  {"mi",       {HB_TAG('M','R','I',' ')}},     /* Maori */
+  {"min",      {HB_TAG('M','I','N',' ')}},     /* Minangkabau */
+  {"mk",       {HB_TAG('M','K','D',' ')}},     /* Macedonian */
+  {"mku",      {HB_TAG('M','N','K',' ')}},     /* Konyanka Maninka -> Maninka */
+  {"mkw",      {HB_TAG('M','K','W',' ')}},     /* Kituba (Congo) */
+  {"ml",       {HB_TAG('M','A','L',' '),       /* Malayalam -> Malayalam Traditional */
+                HB_TAG('M','L','R',' ')}},     /* Malayalam -> Malayalam Reformed */
+  {"mlq",      {HB_TAG('M','L','N',' '),       /* Western Maninkakan -> Malinke */
+                HB_TAG('M','N','K',' ')}},     /* Western Maninkakan -> Maninka */
+  {"mmr",      {HB_TAG('H','M','N',' ')}},     /* Western Xiangxi Miao -> Hmong */
+  {"mn",       {HB_TAG('M','N','G',' ')}},     /* Mongolian [macrolanguage] */
+  {"mnc",      {HB_TAG('M','C','H',' ')}},     /* Manchu */
+  {"mni",      {HB_TAG('M','N','I',' ')}},     /* Manipuri */
+  {"mnk",      {HB_TAG('M','N','D',' '),       /* Mandinka */
+                HB_TAG('M','N','K',' ')}},     /* Mandinka -> Maninka */
+  {"mnp",      {HB_TAG('Z','H','S',' ')}},     /* Min Bei Chinese -> Chinese Simplified */
+  {"mns",      {HB_TAG('M','A','N',' ')}},     /* Mansi */
+  {"mnw",      {HB_TAG('M','O','N',' ')}},     /* Mon */
+  {"mo",       {HB_TAG('M','O','L',' ')}},     /* Moldavian (retired code) */
+  {"moh",      {HB_TAG('M','O','H',' ')}},     /* Mohawk */
+  {"mos",      {HB_TAG('M','O','S',' ')}},     /* Mossi */
+  {"mpe",      {HB_TAG('M','A','J',' ')}},     /* Majang */
+  {"mqg",      {HB_TAG('M','L','Y',' ')}},     /* Kota Bangun Kutai Malay -> Malay */
+  {"mr",       {HB_TAG('M','A','R',' ')}},     /* Marathi */
+  {"mrh",      {HB_TAG('Q','I','N',' ')}},     /* Mara Chin -> Chin */
+  {"mrj",      {HB_TAG('H','M','A',' ')}},     /* Western Mari -> High Mari */
+  {"ms",       {HB_TAG('M','L','Y',' ')}},     /* Malay [macrolanguage] */
+  {"msc",      {HB_TAG('M','N','K',' ')}},     /* Sankaran Maninka -> Maninka */
+  {"msh",      {HB_TAG('M','L','G',' ')}},     /* Masikoro Malagasy -> Malagasy */
+  {"msi",      {HB_TAG('M','L','Y',' ')}},     /* Sabah Malay -> Malay */
+  {"mt",       {HB_TAG('M','T','S',' ')}},     /* Maltese */
+  {"mtr",      {HB_TAG('M','A','W',' ')}},     /* Mewari -> Marwari */
+  {"mui",      {HB_TAG('M','L','Y',' ')}},     /* Musi -> Malay */
+  {"mup",      {HB_TAG('R','A','J',' ')}},     /* Malvi -> Rajasthani */
+  {"muq",      {HB_TAG('H','M','N',' ')}},     /* Eastern Xiangxi Miao -> Hmong */
+  {"mus",      {HB_TAG('M','U','S',' ')}},     /* Creek -> Muscogee */
+  {"mvb",      {HB_TAG('A','T','H',' ')}},     /* Mattole -> Athapaskan */
+  {"mve",      {HB_TAG('M','A','W',' ')}},     /* Marwari (Pakistan) */
+  {"mvf",      {HB_TAG('M','N','G',' ')}},     /* Peripheral Mongolian -> Mongolian */
+  {"mwk",      {HB_TAG('M','N','K',' ')}},     /* Kita Maninkakan -> Maninka */
+  {"mwl",      {HB_TAG('M','W','L',' ')}},     /* Mirandese */
+  {"mwr",      {HB_TAG('M','A','W',' ')}},     /* Marwari [macrolanguage] */
+  {"mww",      {HB_TAG('M','W','W',' ')}},     /* Hmong Daw */
+  {"my",       {HB_TAG('B','R','M',' ')}},     /* Burmese */
+  {"mym",      {HB_TAG('M','E','N',' ')}},     /* Me'en */
+  {"myn",      {HB_TAG('M','Y','N',' ')}},     /* Mayan [family] */
+  {"myq",      {HB_TAG('M','N','K',' ')}},     /* Forest Maninka (retired code) -> Maninka */
+  {"myv",      {HB_TAG('E','R','Z',' ')}},     /* Erzya */
+  {"mzn",      {HB_TAG('M','Z','N',' ')}},     /* Mazanderani */
+  {"na",       {HB_TAG('N','A','U',' ')}},     /* Nauru -> Nauruan */
+  {"nag",      {HB_TAG('N','A','G',' ')}},     /* Naga Pidgin -> Naga-Assamese */
+  {"nah",      {HB_TAG('N','A','H',' ')}},     /* Nahuatl [family] */
+  {"nan",      {HB_TAG('Z','H','S',' ')}},     /* Min Nan Chinese -> Chinese Simplified */
+  {"nap",      {HB_TAG('N','A','P',' ')}},     /* Neapolitan */
+  {"nb",       {HB_TAG('N','O','R',' ')}},     /* Norwegian Bokmål -> Norwegian */
+  {"nd",       {HB_TAG('N','D','B',' ')}},     /* North Ndebele -> Ndebele */
+  {"ndc",      {HB_TAG('N','D','C',' ')}},     /* Ndau */
+  {"nds",      {HB_TAG('N','D','S',' ')}},     /* Low Saxon */
+  {"ne",       {HB_TAG('N','E','P',' ')}},     /* Nepali [macrolanguage] */
+  {"new",      {HB_TAG('N','E','W',' ')}},     /* Newari */
+  {"ng",       {HB_TAG('N','D','G',' ')}},     /* Ndonga */
+  {"nga",      {HB_TAG('N','G','A',' ')}},     /* Ngbaka */
+  {"ngl",      {HB_TAG('L','M','W',' ')}},     /* Lomwe */
+  {"ngo",      {HB_TAG('S','X','T',' ')}},     /* Ngoni -> Sutu */
+  {"nhd",      {HB_TAG('G','U','A',' ')}},     /* Chiripá -> Guarani */
+  {"niq",      {HB_TAG('K','A','L',' ')}},     /* Nandi -> Kalenjin */
+  {"niu",      {HB_TAG('N','I','U',' ')}},     /* Niuean */
+  {"niv",      {HB_TAG('G','I','L',' ')}},     /* Gilyak */
+  {"njz",      {HB_TAG('N','I','S',' ')}},     /* Nyishi -> Nisi */
+  {"nl",       {HB_TAG('N','L','D',' ')}},     /* Dutch */
+  {"nle",      {HB_TAG('L','U','H',' ')}},     /* East Nyala -> Luyia */
+  {"nn",       {HB_TAG('N','Y','N',' ')}},     /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+  {"no",       {HB_TAG('N','O','R',' ')}},     /* Norwegian [macrolanguage] */
+  {"nod",      {HB_TAG('N','T','A',' ')}},     /* Northern Thai -> Northern Tai */
+  {"noe",      {HB_TAG('N','O','E',' ')}},     /* Nimadi */
+  {"nog",      {HB_TAG('N','O','G',' ')}},     /* Nogai */
+  {"nov",      {HB_TAG('N','O','V',' ')}},     /* Novial */
+  {"npi",      {HB_TAG('N','E','P',' ')}},     /* Nepali */
+  {"nqo",      {HB_TAG('N','K','O',' ')}},     /* N'Ko */
+  {"nr",       {HB_TAG('N','D','B',' ')}},     /* South Ndebele -> Ndebele */
+  {"nsk",      {HB_TAG('N','A','S',' ')}},     /* Naskapi */
+  {"nso",      {HB_TAG('N','S','O',' ')}},     /* Pedi -> Sotho, Northern */
+  {"nv",       {HB_TAG('N','A','V',' '),       /* Navajo */
+                HB_TAG('A','T','H',' ')}},     /* Navajo -> Athapaskan */
+  {"ny",       {HB_TAG('C','H','I',' ')}},     /* Chichewa (Chewa, Nyanja) */
+  {"nyd",      {HB_TAG('L','U','H',' ')}},     /* Nyore -> Luyia */
+  {"nym",      {HB_TAG('N','Y','M',' ')}},     /* Nyamwezi */
+  {"nyn",      {HB_TAG('N','K','L',' ')}},     /* Nyankole */
+  {"nza",      {HB_TAG('N','Z','A',' ')}},     /* Tigon Mbembe -> Mbembe Tigon */
+  {"oc",       {HB_TAG('O','C','I',' ')}},     /* Occitan (post 1500) */
+  {"oj",       {HB_TAG('O','J','B',' ')}},     /* Ojibwa [macrolanguage] -> Ojibway */
+  {"ojb",      {HB_TAG('O','J','B',' ')}},     /* Northwestern Ojibwa -> Ojibway */
+  {"ojc",      {HB_TAG('O','J','B',' ')}},     /* Central Ojibwa -> Ojibway */
+  {"ojg",      {HB_TAG('O','J','B',' ')}},     /* Eastern Ojibwa -> Ojibway */
+  {"ojs",      {HB_TAG('O','C','R',' ')}},     /* Severn Ojibwa -> Oji-Cree */
+  {"ojw",      {HB_TAG('O','J','B',' ')}},     /* Western Ojibwa -> Ojibway */
+  {"oki",      {HB_TAG('K','A','L',' ')}},     /* Okiek -> Kalenjin */
+  {"okm",      {HB_TAG('K','O','H',' ')}},     /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+  {"om",       {HB_TAG('O','R','O',' ')}},     /* Oromo [macrolanguage] */
+  {"or",       {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) [macrolanguage] */
+  {"orc",      {HB_TAG('O','R','O',' ')}},     /* Orma -> Oromo */
+  {"orn",      {HB_TAG('M','L','Y',' ')}},     /* Orang Kanaq -> Malay */
+  {"ors",      {HB_TAG('M','L','Y',' ')}},     /* Orang Seletar -> Malay */
+  {"ory",      {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) */
+  {"os",       {HB_TAG('O','S','S',' ')}},     /* Ossetian */
+  {"otw",      {HB_TAG('O','J','B',' ')}},     /* Ottawa -> Ojibway */
+  {"pa",       {HB_TAG('P','A','N',' ')}},     /* Punjabi */
+  {"pag",      {HB_TAG('P','A','G',' ')}},     /* Pangasinan */
+  {"pam",      {HB_TAG('P','A','M',' ')}},     /* Pampanga -> Pampangan */
+  {"pap",      {HB_TAG('P','A','P','0')}},     /* Papiamento -> Papiamentu */
+  {"pau",      {HB_TAG('P','A','U',' ')}},     /* Palauan */
+  {"pbt",      {HB_TAG('P','A','S',' ')}},     /* Southern Pashto -> Pashto */
+  {"pbu",      {HB_TAG('P','A','S',' ')}},     /* Northern Pashto -> Pashto */
+  {"pcc",      {HB_TAG('P','C','C',' ')}},     /* Bouyei */
+  {"pcd",      {HB_TAG('P','C','D',' ')}},     /* Picard */
+  {"pce",      {HB_TAG('P','L','G',' ')}},     /* Ruching Palaung -> Palaung */
+  {"pck",      {HB_TAG('Q','I','N',' ')}},     /* Paite Chin -> Chin */
+  {"pdc",      {HB_TAG('P','D','C',' ')}},     /* Pennsylvania German */
+  {"pel",      {HB_TAG('M','L','Y',' ')}},     /* Pekal -> Malay */
+  {"pes",      {HB_TAG('F','A','R',' ')}},     /* Iranian Persian -> Persian */
+  {"pga",      {HB_TAG('A','R','A',' ')}},     /* Sudanese Creole Arabic -> Arabic */
+  {"phk",      {HB_TAG('P','H','K',' ')}},     /* Phake */
+  {"pi",       {HB_TAG('P','A','L',' ')}},     /* Pali */
+  {"pih",      {HB_TAG('P','I','H',' ')}},     /* Pitcairn-Norfolk -> Norfolk */
+  {"pko",      {HB_TAG('K','A','L',' ')}},     /* Pökoot -> Kalenjin */
+  {"pl",       {HB_TAG('P','L','K',' ')}},     /* Polish */
+  {"pll",      {HB_TAG('P','L','G',' ')}},     /* Shwe Palaung -> Palaung */
+  {"plp",      {HB_TAG('P','A','P',' ')}},     /* Palpa */
+  {"plt",      {HB_TAG('M','L','G',' ')}},     /* Plateau Malagasy -> Malagasy */
+  {"pms",      {HB_TAG('P','M','S',' ')}},     /* Piemontese */
+  {"pnb",      {HB_TAG('P','N','B',' ')}},     /* Western Panjabi */
+  {"poh",      {HB_TAG('P','O','H',' ')}},     /* Poqomchi' -> Pocomchi */
+  {"pon",      {HB_TAG('P','O','N',' ')}},     /* Pohnpeian */
+  {"ppa",      {HB_TAG('B','A','G',' ')}},     /* Pao (retired code) -> Baghelkhandi */
+  {"pro",      {HB_TAG('P','R','O',' ')}},     /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+  {"prs",      {HB_TAG('D','R','I',' ')}},     /* Dari */
+  {"ps",       {HB_TAG('P','A','S',' ')}},     /* Pashto [macrolanguage] */
+  {"pse",      {HB_TAG('M','L','Y',' ')}},     /* Central Malay -> Malay */
+  {"pst",      {HB_TAG('P','A','S',' ')}},     /* Central Pashto -> Pashto */
+  {"pt",       {HB_TAG('P','T','G',' ')}},     /* Portuguese */
+  {"pwo",      {HB_TAG('P','W','O',' ')}},     /* Pwo Western Karen -> Western Pwo Karen */
+  {"qu",       {HB_TAG('Q','U','Z',' ')}},     /* Quechua [macrolanguage] */
+  {"qub",      {HB_TAG('Q','W','H',' ')}},     /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+  {"quc",      {HB_TAG('Q','U','C',' ')}},     /* K’iche’ */
+  {"qud",      {HB_TAG('Q','V','I',' ')}},     /* Calderón Highland Quichua -> Quechua (Ecuador) */
+  {"quf",      {HB_TAG('Q','U','Z',' ')}},     /* Lambayeque Quechua -> Quechua */
+  {"qug",      {HB_TAG('Q','V','I',' ')}},     /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+  {"quh",      {HB_TAG('Q','U','H',' ')}},     /* South Bolivian Quechua -> Quechua (Bolivia) */
+  {"quk",      {HB_TAG('Q','U','Z',' ')}},     /* Chachapoyas Quechua -> Quechua */
+  {"qul",      {HB_TAG('Q','U','Z',' ')}},     /* North Bolivian Quechua -> Quechua */
+  {"qup",      {HB_TAG('Q','V','I',' ')}},     /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+  {"qur",      {HB_TAG('Q','W','H',' ')}},     /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+  {"qus",      {HB_TAG('Q','U','H',' ')}},     /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+  {"quw",      {HB_TAG('Q','V','I',' ')}},     /* Tena Lowland Quichua -> Quechua (Ecuador) */
+  {"qux",      {HB_TAG('Q','W','H',' ')}},     /* Yauyos Quechua -> Quechua (Peru) */
+  {"quy",      {HB_TAG('Q','U','Z',' ')}},     /* Ayacucho Quechua -> Quechua */
+  {"quz",      {HB_TAG('Q','U','Z',' ')}},     /* Cusco Quechua -> Quechua */
+  {"qva",      {HB_TAG('Q','W','H',' ')}},     /* Ambo-Pasco Quechua -> Quechua (Peru) */
+  {"qvc",      {HB_TAG('Q','U','Z',' ')}},     /* Cajamarca Quechua -> Quechua */
+  {"qve",      {HB_TAG('Q','U','Z',' ')}},     /* Eastern Apurímac Quechua -> Quechua */
+  {"qvh",      {HB_TAG('Q','W','H',' ')}},     /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+  {"qvi",      {HB_TAG('Q','V','I',' ')}},     /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+  {"qvj",      {HB_TAG('Q','V','I',' ')}},     /* Loja Highland Quichua -> Quechua (Ecuador) */
+  {"qvl",      {HB_TAG('Q','W','H',' ')}},     /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+  {"qvm",      {HB_TAG('Q','W','H',' ')}},     /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+  {"qvn",      {HB_TAG('Q','W','H',' ')}},     /* North Junín Quechua -> Quechua (Peru) */
+  {"qvo",      {HB_TAG('Q','V','I',' ')}},     /* Napo Lowland Quechua -> Quechua (Ecuador) */
+  {"qvp",      {HB_TAG('Q','W','H',' ')}},     /* Pacaraos Quechua -> Quechua (Peru) */
+  {"qvs",      {HB_TAG('Q','U','Z',' ')}},     /* San Martín Quechua -> Quechua */
+  {"qvw",      {HB_TAG('Q','W','H',' ')}},     /* Huaylla Wanca Quechua -> Quechua (Peru) */
+  {"qvz",      {HB_TAG('Q','V','I',' ')}},     /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+  {"qwa",      {HB_TAG('Q','W','H',' ')}},     /* Corongo Ancash Quechua -> Quechua (Peru) */
+  {"qwc",      {HB_TAG('Q','U','Z',' ')}},     /* Classical Quechua -> Quechua */
+  {"qwh",      {HB_TAG('Q','W','H',' ')}},     /* Huaylas Ancash Quechua -> Quechua (Peru) */
+  {"qws",      {HB_TAG('Q','W','H',' ')}},     /* Sihuas Ancash Quechua -> Quechua (Peru) */
+  {"qxa",      {HB_TAG('Q','W','H',' ')}},     /* Chiquián Ancash Quechua -> Quechua (Peru) */
+  {"qxc",      {HB_TAG('Q','W','H',' ')}},     /* Chincha Quechua -> Quechua (Peru) */
+  {"qxh",      {HB_TAG('Q','W','H',' ')}},     /* Panao Huánuco Quechua -> Quechua (Peru) */
+  {"qxl",      {HB_TAG('Q','V','I',' ')}},     /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+  {"qxn",      {HB_TAG('Q','W','H',' ')}},     /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxo",      {HB_TAG('Q','W','H',' ')}},     /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxp",      {HB_TAG('Q','U','Z',' ')}},     /* Puno Quechua -> Quechua */
+  {"qxr",      {HB_TAG('Q','V','I',' ')}},     /* Cañar Highland Quichua -> Quechua (Ecuador) */
+  {"qxt",      {HB_TAG('Q','W','H',' ')}},     /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+  {"qxu",      {HB_TAG('Q','U','Z',' ')}},     /* Arequipa-La Unión Quechua -> Quechua */
+  {"qxw",      {HB_TAG('Q','W','H',' ')}},     /* Jauja Wanca Quechua -> Quechua (Peru) */
+  {"rag",      {HB_TAG('L','U','H',' ')}},     /* Logooli -> Luyia */
+  {"raj",      {HB_TAG('R','A','J',' ')}},     /* Rajasthani [macrolanguage] */
+  {"rar",      {HB_TAG('R','A','R',' ')}},     /* Rarotongan */
+  {"rbb",      {HB_TAG('P','L','G',' ')}},     /* Rumai Palaung -> Palaung */
+  {"rbl",      {HB_TAG('B','I','K',' ')}},     /* Miraya Bikol -> Bikol */
+  {"rej",      {HB_TAG('R','E','J',' ')}},     /* Rejang */
+  {"ria",      {HB_TAG('R','I','A',' ')}},     /* Riang (India) */
+  {"rif",      {HB_TAG('R','I','F',' ')}},     /* Tarifit */
+  {"rit",      {HB_TAG('R','I','T',' ')}},     /* Ritarungo */
+  {"rki",      {HB_TAG('A','R','K',' ')}},     /* Rakhine */
+  {"rkw",      {HB_TAG('R','K','W',' ')}},     /* Arakwal */
+  {"rm",       {HB_TAG('R','M','S',' ')}},     /* Romansh */
+  {"rmc",      {HB_TAG('R','O','Y',' ')}},     /* Carpathian Romani -> Romany */
+  {"rmf",      {HB_TAG('R','O','Y',' ')}},     /* Kalo Finnish Romani -> Romany */
+  {"rml",      {HB_TAG('R','O','Y',' ')}},     /* Baltic Romani -> Romany */
+  {"rmn",      {HB_TAG('R','O','Y',' ')}},     /* Balkan Romani -> Romany */
+  {"rmo",      {HB_TAG('R','O','Y',' ')}},     /* Sinte Romani -> Romany */
+  {"rmw",      {HB_TAG('R','O','Y',' ')}},     /* Welsh Romani -> Romany */
+  {"rmy",      {HB_TAG('R','M','Y',' ')}},     /* Vlax Romani */
+  {"rmz",      {HB_TAG('A','R','K',' ')}},     /* Marma -> Rakhine */
+  {"rn",       {HB_TAG('R','U','N',' ')}},     /* Rundi */
+  {"rnl",      {HB_TAG('H','A','L',' ')}},     /* Ranglong -> Halam (Falam Chin) */
+  {"ro",       {HB_TAG('R','O','M',' ')}},     /* Romanian */
+  {"rom",      {HB_TAG('R','O','Y',' ')}},     /* Romany [macrolanguage] */
+  {"rtm",      {HB_TAG('R','T','M',' ')}},     /* Rotuman */
+  {"ru",       {HB_TAG('R','U','S',' ')}},     /* Russian */
+  {"rue",      {HB_TAG('R','S','Y',' ')}},     /* Rusyn */
+  {"rup",      {HB_TAG('R','U','P',' ')}},     /* Aromanian */
+  {"rw",       {HB_TAG('R','U','A',' ')}},     /* Kinyarwanda */
+  {"rwr",      {HB_TAG('M','A','W',' ')}},     /* Marwari (India) */
+  {"sa",       {HB_TAG('S','A','N',' ')}},     /* Sanskrit */
+  {"sah",      {HB_TAG('Y','A','K',' ')}},     /* Yakut -> Sakha */
+  {"sam",      {HB_TAG('P','A','A',' ')}},     /* Samaritan Aramaic -> Palestinian Aramaic */
+  {"sas",      {HB_TAG('S','A','S',' ')}},     /* Sasak */
+  {"sat",      {HB_TAG('S','A','T',' ')}},     /* Santali */
+  {"sc",       {HB_TAG('S','R','D',' ')}},     /* Sardinian [macrolanguage] */
+  {"sck",      {HB_TAG('S','A','D',' ')}},     /* Sadri */
+  {"scn",      {HB_TAG('S','C','N',' ')}},     /* Sicilian */
+  {"sco",      {HB_TAG('S','C','O',' ')}},     /* Scots */
+  {"scs",      {HB_TAG('S','C','S',' '),       /* North Slavey */
+                HB_TAG('S','L','A',' '),       /* North Slavey -> Slavey */
+                HB_TAG('A','T','H',' ')}},     /* North Slavey -> Athapaskan */
+  {"sd",       {HB_TAG('S','N','D',' ')}},     /* Sindhi */
+  {"sdc",      {HB_TAG('S','R','D',' ')}},     /* Sassarese Sardinian -> Sardinian */
+  {"sdh",      {HB_TAG('K','U','R',' ')}},     /* Southern Kurdish -> Kurdish */
+  {"sdn",      {HB_TAG('S','R','D',' ')}},     /* Gallurese Sardinian -> Sardinian */
+  {"se",       {HB_TAG('N','S','M',' ')}},     /* Northern Sami */
+  {"seh",      {HB_TAG('S','N','A',' ')}},     /* Sena */
+  {"sek",      {HB_TAG('A','T','H',' ')}},     /* Sekani -> Athapaskan */
+  {"sel",      {HB_TAG('S','E','L',' ')}},     /* Selkup */
+  {"sez",      {HB_TAG('Q','I','N',' ')}},     /* Senthang Chin -> Chin */
+  {"sfm",      {HB_TAG('H','M','N',' ')}},     /* Small Flowery Miao -> Hmong */
+  {"sg",       {HB_TAG('S','G','O',' ')}},     /* Sango */
+  {"sga",      {HB_TAG('S','G','A',' ')}},     /* Old Irish (to 900) */
+  {"sgc",      {HB_TAG('K','A','L',' ')}},     /* Kipsigis -> Kalenjin */
+  {"sgs",      {HB_TAG('S','G','S',' ')}},     /* Samogitian */
+  {"sgw",      {HB_TAG('C','H','G',' '),       /* Sebat Bet Gurage -> Chaha Gurage */
+                HB_TAG('S','G','W',' ')}},     /* Sebat Bet Gurage -> Chaha Gurage (SIL fonts) */
+  {"shi",      {HB_TAG('S','H','I',' ')}},     /* Tachelhit */
+  {"shn",      {HB_TAG('S','H','N',' ')}},     /* Shan */
+  {"shu",      {HB_TAG('A','R','A',' ')}},     /* Chadian Arabic -> Arabic */
+  {"si",       {HB_TAG('S','N','H',' ')}},     /* Sinhala (Sinhalese) */
+  {"sid",      {HB_TAG('S','I','D',' ')}},     /* Sidamo */
+  {"sjd",      {HB_TAG('K','S','M',' ')}},     /* Kildin Sami */
+  {"sjo",      {HB_TAG('S','I','B',' ')}},     /* Xibe -> Sibe */
+  {"sk",       {HB_TAG('S','K','Y',' ')}},     /* Slovak */
+  {"skg",      {HB_TAG('M','L','G',' ')}},     /* Sakalava Malagasy -> Malagasy */
+  {"skr",      {HB_TAG('S','R','K',' ')}},     /* Saraiki */
+  {"sl",       {HB_TAG('S','L','V',' ')}},     /* Slovenian */
+  {"sm",       {HB_TAG('S','M','O',' ')}},     /* Samoan */
+  {"sma",      {HB_TAG('S','S','M',' ')}},     /* Southern Sami */
+  {"smj",      {HB_TAG('L','S','M',' ')}},     /* Lule Sami */
+  {"smn",      {HB_TAG('I','S','M',' ')}},     /* Inari Sami */
+  {"sms",      {HB_TAG('S','K','S',' ')}},     /* Skolt Sami */
+  {"sn",       {HB_TAG('S','N','A','0')}},     /* Shona */
+  {"snk",      {HB_TAG('S','N','K',' ')}},     /* Soninke */
+  {"so",       {HB_TAG('S','M','L',' ')}},     /* Somali */
+  {"sop",      {HB_TAG('S','O','P',' ')}},     /* Songe */
+  {"spv",      {HB_TAG('O','R','I',' ')}},     /* Sambalpuri -> Odia (formerly Oriya) */
+  {"spy",      {HB_TAG('K','A','L',' ')}},     /* Sabaot -> Kalenjin */
+  {"sq",       {HB_TAG('S','Q','I',' ')}},     /* Albanian [macrolanguage] */
+  {"sr",       {HB_TAG('S','R','B',' ')}},     /* Serbian */
+  {"src",      {HB_TAG('S','R','D',' ')}},     /* Logudorese Sardinian -> Sardinian */
+  {"sro",      {HB_TAG('S','R','D',' ')}},     /* Campidanese Sardinian -> Sardinian */
+  {"srr",      {HB_TAG('S','R','R',' ')}},     /* Serer */
+  {"srs",      {HB_TAG('A','T','H',' ')}},     /* Sarsi -> Athapaskan */
+  {"ss",       {HB_TAG('S','W','Z',' ')}},     /* Swati */
+  {"ssh",      {HB_TAG('A','R','A',' ')}},     /* Shihhi Arabic -> Arabic */
+  {"st",       {HB_TAG('S','O','T',' ')}},     /* Southern Sotho -> Sotho, Southern */
+  {"stq",      {HB_TAG('S','T','Q',' ')}},     /* Saterfriesisch -> Saterland Frisian */
+  {"stv",      {HB_TAG('S','I','G',' ')}},     /* Silt'e -> Silte Gurage */
+  {"su",       {HB_TAG('S','U','N',' ')}},     /* Sundanese */
+  {"suk",      {HB_TAG('S','U','K',' ')}},     /* Sukuma */
+  {"suq",      {HB_TAG('S','U','R',' ')}},     /* Suri */
+  {"sv",       {HB_TAG('S','V','E',' ')}},     /* Swedish */
+  {"sva",      {HB_TAG('S','V','A',' ')}},     /* Svan */
+  {"sw",       {HB_TAG('S','W','K',' ')}},     /* Swahili [macrolanguage] */
+  {"swb",      {HB_TAG('C','M','R',' ')}},     /* Maore Comorian -> Comorian */
+  {"swc",      {HB_TAG('S','W','K',' ')}},     /* Congo Swahili -> Swahili */
+  {"swh",      {HB_TAG('S','W','K',' ')}},     /* Swahili */
+  {"swv",      {HB_TAG('M','A','W',' ')}},     /* Shekhawati -> Marwari */
+  {"sxu",      {HB_TAG('S','X','U',' ')}},     /* Upper Saxon */
+  {"syc",      {HB_TAG('S','Y','R',' ')}},     /* Classical Syriac -> Syriac */
+  {"syl",      {HB_TAG('S','Y','L',' ')}},     /* Sylheti */
+  {"syr",      {HB_TAG('S','Y','R',' ')}},     /* Syriac [macrolanguage] */
+  {"szl",      {HB_TAG('S','Z','L',' ')}},     /* Silesian */
+  {"ta",       {HB_TAG('T','A','M',' ')}},     /* Tamil */
+  {"taa",      {HB_TAG('A','T','H',' ')}},     /* Lower Tanana -> Athapaskan */
+  {"tab",      {HB_TAG('T','A','B',' ')}},     /* Tabassaran -> Tabasaran */
+  {"taq",      {HB_TAG('T','M','H',' ')}},     /* Tamasheq -> Tamashek */
+  {"tau",      {HB_TAG('A','T','H',' ')}},     /* Upper Tanana -> Athapaskan */
+  {"tcb",      {HB_TAG('A','T','H',' ')}},     /* Tanacross -> Athapaskan */
+  {"tce",      {HB_TAG('A','T','H',' ')}},     /* Southern Tutchone -> Athapaskan */
+  {"tcp",      {HB_TAG('Q','I','N',' ')}},     /* Tawr Chin -> Chin */
+  {"tcy",      {HB_TAG('T','U','L',' ')}},     /* Tulu -> Tumbuka */
+  {"tcz",      {HB_TAG('Q','I','N',' ')}},     /* Thado Chin -> Chin */
+  {"tdd",      {HB_TAG('T','D','D',' ')}},     /* Tai Nüa -> Dehong Dai */
+  {"tdx",      {HB_TAG('M','L','G',' ')}},     /* Tandroy-Mahafaly Malagasy -> Malagasy */
+  {"te",       {HB_TAG('T','E','L',' ')}},     /* Telugu */
+  {"tec",      {HB_TAG('K','A','L',' ')}},     /* Terik -> Kalenjin */
+  {"tem",      {HB_TAG('T','M','N',' ')}},     /* Timne -> Temne */
+  {"tet",      {HB_TAG('T','E','T',' ')}},     /* Tetum */
+  {"tfn",      {HB_TAG('A','T','H',' ')}},     /* Tanaina -> Athapaskan */
+  {"tg",       {HB_TAG('T','A','J',' ')}},     /* Tajik -> Tajiki */
+  {"tgj",      {HB_TAG('N','I','S',' ')}},     /* Tagin -> Nisi */
+  {"tgx",      {HB_TAG('A','T','H',' ')}},     /* Tagish -> Athapaskan */
+  {"th",       {HB_TAG('T','H','A',' ')}},     /* Thai */
+  {"tht",      {HB_TAG('A','T','H',' ')}},     /* Tahltan -> Athapaskan */
+  {"thv",      {HB_TAG('T','M','H',' ')}},     /* Tahaggart Tamahaq -> Tamashek */
+  {"thz",      {HB_TAG('T','M','H',' ')}},     /* Tayart Tamajeq -> Tamashek */
+  {"ti",       {HB_TAG('T','G','Y',' ')}},     /* Tigrinya */
+  {"tig",      {HB_TAG('T','G','R',' ')}},     /* Tigre */
+  {"tiv",      {HB_TAG('T','I','V',' ')}},     /* Tiv */
+  {"tk",       {HB_TAG('T','K','M',' ')}},     /* Turkmen */
+  {"tkg",      {HB_TAG('M','L','G',' ')}},     /* Tesaka Malagasy -> Malagasy */
+  {"tl",       {HB_TAG('T','G','L',' ')}},     /* Tagalog */
+  {"tmh",      {HB_TAG('T','M','H',' ')}},     /* Tamashek [macrolanguage] */
+  {"tmw",      {HB_TAG('M','L','Y',' ')}},     /* Temuan -> Malay */
+  {"tn",       {HB_TAG('T','N','A',' ')}},     /* Tswana */
+  {"tnf",      {HB_TAG('D','R','I',' ')}},     /* Tangshewi (retired code) -> Dari */
+  {"to",       {HB_TAG('T','G','N',' ')}},     /* Tonga (Tonga Islands) -> Tongan */
+  {"tod",      {HB_TAG('T','O','D','0')}},     /* Toma */
+  {"toi",      {HB_TAG('T','N','G',' ')}},     /* Tonga (Zambia) */
+  {"tol",      {HB_TAG('A','T','H',' ')}},     /* Tolowa -> Athapaskan */
+  {"tpi",      {HB_TAG('T','P','I',' ')}},     /* Tok Pisin */
+  {"tr",       {HB_TAG('T','R','K',' ')}},     /* Turkish */
+  {"tru",      {HB_TAG('T','U','A',' '),       /* Turoyo -> Turoyo Aramaic */
+                HB_TAG('S','Y','R',' ')}},     /* Turoyo -> Syriac */
+  {"ts",       {HB_TAG('T','S','G',' ')}},     /* Tsonga */
+  {"tsj",      {HB_TAG('T','S','J',' ')}},     /* Tshangla */
+  {"tt",       {HB_TAG('T','A','T',' ')}},     /* Tatar */
+  {"ttm",      {HB_TAG('A','T','H',' ')}},     /* Northern Tutchone -> Athapaskan */
+  {"ttq",      {HB_TAG('T','M','H',' ')}},     /* Tawallammat Tamajaq -> Tamashek */
+  {"tum",      {HB_TAG('T','U','M',' ')}},     /* Tumbuka -> Tulu */
+  {"tuu",      {HB_TAG('A','T','H',' ')}},     /* Tututni -> Athapaskan */
+  {"tuy",      {HB_TAG('K','A','L',' ')}},     /* Tugen -> Kalenjin */
+  {"tvl",      {HB_TAG('T','V','L',' ')}},     /* Tuvalu */
+  {"tw",       {HB_TAG('T','W','I',' '),       /* Twi */
+                HB_TAG('A','K','A',' ')}},     /* Twi -> Akan */
+  {"txc",      {HB_TAG('A','T','H',' ')}},     /* Tsetsaut -> Athapaskan */
+  {"txy",      {HB_TAG('M','L','G',' ')}},     /* Tanosy Malagasy -> Malagasy */
+  {"ty",       {HB_TAG('T','H','T',' ')}},     /* Tahitian */
+  {"tyv",      {HB_TAG('T','U','V',' ')}},     /* Tuvinian -> Tuvin */
+  {"tyz",      {HB_TAG('T','Y','Z',' ')}},     /* Tày */
+  {"tzm",      {HB_TAG('T','Z','M',' ')}},     /* Central Atlas Tamazight -> Tamazight */
+  {"tzo",      {HB_TAG('T','Z','O',' ')}},     /* Tzotzil */
+  {"ubl",      {HB_TAG('B','I','K',' ')}},     /* Buhi'non Bikol -> Bikol */
+  {"udm",      {HB_TAG('U','D','M',' ')}},     /* Udmurt */
+  {"ug",       {HB_TAG('U','Y','G',' ')}},     /* Uyghur */
+  {"uk",       {HB_TAG('U','K','R',' ')}},     /* Ukrainian */
+  {"umb",      {HB_TAG('U','M','B',' ')}},     /* Umbundu */
+  {"unr",      {HB_TAG('M','U','N',' ')}},     /* Mundari */
+  {"ur",       {HB_TAG('U','R','D',' ')}},     /* Urdu */
+  {"urk",      {HB_TAG('M','L','Y',' ')}},     /* Urak Lawoi' -> Malay */
+  {"uz",       {HB_TAG('U','Z','B',' ')}},     /* Uzbek [macrolanguage] */
+  {"uzn",      {HB_TAG('U','Z','B',' ')}},     /* Northern Uzbek -> Uzbek */
+  {"uzs",      {HB_TAG('U','Z','B',' ')}},     /* Southern Uzbek -> Uzbek */
+  {"ve",       {HB_TAG('V','E','N',' ')}},     /* Venda */
+  {"vec",      {HB_TAG('V','E','C',' ')}},     /* Venetian */
+  {"vi",       {HB_TAG('V','I','T',' ')}},     /* Vietnamese */
+  {"vkk",      {HB_TAG('M','L','Y',' ')}},     /* Kaur -> Malay */
+  {"vkt",      {HB_TAG('M','L','Y',' ')}},     /* Tenggarong Kutai Malay -> Malay */
+  {"vls",      {HB_TAG('F','L','E',' ')}},     /* Vlaams -> Dutch (Flemish) */
+  {"vmw",      {HB_TAG('M','A','K',' ')}},     /* Makhuwa */
+  {"vo",       {HB_TAG('V','O','L',' ')}},     /* Volapük */
+  {"vro",      {HB_TAG('V','R','O',' ')}},     /* Võro */
+  {"wa",       {HB_TAG('W','L','N',' ')}},     /* Walloon */
+  {"war",      {HB_TAG('W','A','R',' ')}},     /* Waray (Philippines) -> Waray-Waray */
+  {"wbm",      {HB_TAG('W','A',' ',' ')}},     /* Wa */
+  {"wbr",      {HB_TAG('W','A','G',' ')}},     /* Wagdi */
+  {"wlc",      {HB_TAG('C','M','R',' ')}},     /* Mwali Comorian -> Comorian */
+  {"wle",      {HB_TAG('S','I','G',' ')}},     /* Wolane -> Silte Gurage */
+  {"wlk",      {HB_TAG('A','T','H',' ')}},     /* Wailaki -> Athapaskan */
+  {"wni",      {HB_TAG('C','M','R',' ')}},     /* Ndzwani Comorian -> Comorian */
+  {"wo",       {HB_TAG('W','L','F',' ')}},     /* Wolof */
+  {"wry",      {HB_TAG('M','A','W',' ')}},     /* Merwari -> Marwari */
+  {"wsg",      {HB_TAG('G','O','N',' ')}},     /* Adilabad Gondi -> Gondi */
+  {"wtm",      {HB_TAG('W','T','M',' ')}},     /* Mewati */
+  {"wuu",      {HB_TAG('Z','H','S',' ')}},     /* Wu Chinese -> Chinese Simplified */
+  {"xal",      {HB_TAG('K','L','M',' '),       /* Kalmyk */
+                HB_TAG('T','O','D',' ')}},     /* Kalmyk -> Todo */
+  {"xan",      {HB_TAG('S','E','K',' ')}},     /* Xamtanga -> Sekota */
+  {"xh",       {HB_TAG('X','H','S',' ')}},     /* Xhosa */
+  {"xjb",      {HB_TAG('X','J','B',' ')}},     /* Minjungbal -> Minjangbal */
+  {"xkf",      {HB_TAG('X','K','F',' ')}},     /* Khengkha */
+  {"xmm",      {HB_TAG('M','L','Y',' ')}},     /* Manado Malay -> Malay */
+  {"xmv",      {HB_TAG('M','L','G',' ')}},     /* Antankarana Malagasy -> Malagasy */
+  {"xmw",      {HB_TAG('M','L','G',' ')}},     /* Tsimihety Malagasy -> Malagasy */
+  {"xnr",      {HB_TAG('D','G','R',' ')}},     /* Kangri -> Dogri */
+  {"xog",      {HB_TAG('X','O','G',' ')}},     /* Soga */
+  {"xpe",      {HB_TAG('X','P','E',' ')}},     /* Liberia Kpelle -> Kpelle (Liberia) */
+  {"xsl",      {HB_TAG('S','S','L',' '),       /* South Slavey */
+                HB_TAG('S','L','A',' '),       /* South Slavey -> Slavey */
+                HB_TAG('A','T','H',' ')}},     /* South Slavey -> Athapaskan */
+  {"xst",      {HB_TAG('S','I','G',' ')}},     /* Silt'e (retired code) -> Silte Gurage */
+  {"xwo",      {HB_TAG('T','O','D',' ')}},     /* Written Oirat -> Todo */
+  {"yao",      {HB_TAG('Y','A','O',' ')}},     /* Yao */
+  {"yap",      {HB_TAG('Y','A','P',' ')}},     /* Yapese */
+  {"ybd",      {HB_TAG('A','R','K',' ')}},     /* Yangbye (retired code) -> Rakhine */
+  {"ydd",      {HB_TAG('J','I','I',' ')}},     /* Eastern Yiddish -> Yiddish */
+  {"yi",       {HB_TAG('J','I','I',' ')}},     /* Yiddish [macrolanguage] */
+  {"yih",      {HB_TAG('J','I','I',' ')}},     /* Western Yiddish -> Yiddish */
+  {"yo",       {HB_TAG('Y','B','A',' ')}},     /* Yoruba */
+  {"yos",      {HB_TAG('Q','I','N',' ')}},     /* Yos (retired code) -> Chin */
+  {"yrk",      {HB_TAG('T','N','E',' '),       /* Nenets -> Tundra Nenets */
+                HB_TAG('F','N','E',' ')}},     /* Nenets -> Forest Nenets */
+  {"yue",      {HB_TAG('Z','H','H',' ')}},     /* Yue Chinese -> Chinese, Hong Kong SAR */
+  {"za",       {HB_TAG('Z','H','A',' ')}},     /* Zhuang [macrolanguage] */
+  {"zch",      {HB_TAG('Z','H','A',' ')}},     /* Central Hongshuihe Zhuang -> Zhuang */
+  {"zdj",      {HB_TAG('C','M','R',' ')}},     /* Ngazidja Comorian -> Comorian */
+  {"zea",      {HB_TAG('Z','E','A',' ')}},     /* Zeeuws -> Zealandic */
+  {"zeh",      {HB_TAG('Z','H','A',' ')}},     /* Eastern Hongshuihe Zhuang -> Zhuang */
+  {"zgb",      {HB_TAG('Z','H','A',' ')}},     /* Guibei Zhuang -> Zhuang */
+  {"zgh",      {HB_TAG('Z','G','H',' ')}},     /* Standard Moroccan Tamazight */
+  {"zgm",      {HB_TAG('Z','H','A',' ')}},     /* Minz Zhuang -> Zhuang */
+  {"zgn",      {HB_TAG('Z','H','A',' ')}},     /* Guibian Zhuang -> Zhuang */
+  {"zh",       {HB_TAG('Z','H','S',' ')}},     /* Chinese [macrolanguage] -> Chinese Simplified */
+  {"zhd",      {HB_TAG('Z','H','A',' ')}},     /* Dai Zhuang -> Zhuang */
+  {"zhn",      {HB_TAG('Z','H','A',' ')}},     /* Nong Zhuang -> Zhuang */
+  {"zlj",      {HB_TAG('Z','H','A',' ')}},     /* Liujiang Zhuang -> Zhuang */
+  {"zlm",      {HB_TAG('M','L','Y',' ')}},     /* Malay */
+  {"zln",      {HB_TAG('Z','H','A',' ')}},     /* Lianshan Zhuang -> Zhuang */
+  {"zlq",      {HB_TAG('Z','H','A',' ')}},     /* Liuqian Zhuang -> Zhuang */
+  {"zmi",      {HB_TAG('M','L','Y',' ')}},     /* Negeri Sembilan Malay -> Malay */
+  {"zne",      {HB_TAG('Z','N','D',' ')}},     /* Zande */
+  {"zom",      {HB_TAG('Q','I','N',' ')}},     /* Zou -> Chin */
+  {"zqe",      {HB_TAG('Z','H','A',' ')}},     /* Qiubei Zhuang -> Zhuang */
+  {"zsm",      {HB_TAG('M','L','Y',' ')}},     /* Standard Malay -> Malay */
+  {"zu",       {HB_TAG('Z','U','L',' ')}},     /* Zulu */
+  {"zum",      {HB_TAG('L','R','C',' ')}},     /* Kumzari -> Luri */
+  {"zyb",      {HB_TAG('Z','H','A',' ')}},     /* Yongbei Zhuang -> Zhuang */
+  {"zyg",      {HB_TAG('Z','H','A',' ')}},     /* Yang Zhuang -> Zhuang */
+  {"zyj",      {HB_TAG('Z','H','A',' ')}},     /* Youjiang Zhuang -> Zhuang */
+  {"zyn",      {HB_TAG('Z','H','A',' ')}},     /* Yongnan Zhuang -> Zhuang */
+  {"zza",      {HB_TAG('Z','Z','A',' ')}},     /* Zazaki [macrolanguage] */
+  {"zzj",      {HB_TAG('Z','H','A',' ')}},     /* Zuojiang Zhuang -> Zhuang */
+};
+
+static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == 3u, "");
+
+/**
+ * hb_ot_tags_from_complex_language:
+ * @lang_str: a BCP 47 language tag to convert.
+ * @limit: a pointer to the end of the substring of @lang_str to consider for
+ * conversion.
+ * @count: maximum number of language tags to retrieve (IN) and actual number of
+ * language tags retrieved (OUT). If no tags are retrieved, it is not modified.
+ * @tags: array of size at least @language_count to store the language tag
+ * results
+ *
+ * Converts a multi-subtag BCP 47 language tag to language tags.
+ *
+ * Return value: Whether any language systems were retrieved.
+ **/
+static bool
+hb_ot_tags_from_complex_language (const char   *lang_str,
+                                 const char   *limit,
+                                 unsigned int *count /* IN/OUT */,
+                                 hb_tag_t     *tags /* OUT */)
+{
+  if (subtag_matches (lang_str, limit, "-fonnapa"))
+  {
+    /* Undetermined; North American Phonetic Alphabet */
+    tags[0] = HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-polyton"))
+  {
+    /* Modern Greek (1453-); Polytonic Greek */
+    tags[0] = HB_TAG('P','G','R',' ');  /* Polytonic Greek */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-provenc"))
+  {
+    /* Occitan (post 1500); Provençal */
+    tags[0] = HB_TAG('P','R','O',' ');  /* Provençal / Old Provençal */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-fonipa"))
+  {
+    /* Undetermined; International Phonetic Alphabet */
+    tags[0] = HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-geok"))
+  {
+    /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+    tags[0] = HB_TAG('K','G','E',' ');  /* Khutsuri Georgian */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syre"))
+  {
+    /* Undetermined; Syriac (Estrangelo variant) */
+    tags[0] = HB_TAG('S','Y','R','E');  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrj"))
+  {
+    /* Undetermined; Syriac (Western variant) */
+    tags[0] = HB_TAG('S','Y','R','J');  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrn"))
+  {
+    /* Undetermined; Syriac (Eastern variant) */
+    tags[0] = HB_TAG('S','Y','R','N');  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    *count = 1;
+    return true;
+  }
+  switch (lang_str[0])
+  {
+  case 'a':
+    if (0 == strcmp (&lang_str[1], "rt-lojban"))
+    {
+      /* Lojban */
+      tags[0] = HB_TAG('J','B','O',' ');  /* Lojban */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'c':
+    if (lang_matches (&lang_str[1], "do-hant-hk"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant-mo"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-hk"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-mo"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-hk"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-mo"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-hk"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-mo"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-hk"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-mo"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-hk"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-mo"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hans"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hans"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hans"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hans"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hans"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Dong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Dong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Dong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Jinyu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Jinyu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Jinyu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Mandarin Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Mandarin Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Mandarin Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Pu-Xian Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Pu-Xian Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Pu-Xian Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Huizhou Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Huizhou Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Huizhou Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Zhong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Zhong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Zhong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'g':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "a-latg"))
+    {
+      /* Irish */
+      tags[0] = HB_TAG('I','R','T',' ');  /* Irish Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Gan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Gan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Gan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'h':
+    if (lang_matches (&lang_str[1], "ak-hant-hk"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant-mo"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-hk"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-mo"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hans"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hans"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Hakka Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Hakka Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Hakka Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Xiang Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Xiang Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Xiang Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'i':
+    if (0 == strcmp (&lang_str[1], "-navajo"))
+    {
+      /* Navajo */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+       HB_TAG('N','A','V',' '),  /* Navajo */
+       HB_TAG('A','T','H',' '),  /* Athapaskan */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+       tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-hak"))
+    {
+      /* Hakka */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-lux"))
+    {
+      /* Luxembourgish */
+      tags[0] = HB_TAG('L','T','Z',' ');  /* Luxembourgish */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'l':
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Literary Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'm':
+    if (lang_matches (&lang_str[1], "np-hant-hk"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant-mo"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hans"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Bei Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Bei Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Bei Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'n':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Nan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Nan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Nan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-bok"))
+    {
+      /* Norwegian Bokmal */
+      tags[0] = HB_TAG('N','O','R',' ');  /* Norwegian */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-nyn"))
+    {
+      /* Norwegian Nynorsk */
+      tags[0] = HB_TAG('N','Y','N',' ');  /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'r':
+    if (0 == strncmp (&lang_str[1], "o-", 2)
+       && subtag_matches (lang_str, limit, "-md"))
+    {
+      /* Romanian; Moldova */
+      tags[0] = HB_TAG('M','O','L',' ');  /* Moldavian */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'w':
+    if (lang_matches (&lang_str[1], "uu-hant-hk"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant-mo"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hans"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Wu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Wu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Wu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'y':
+    if (lang_matches (&lang_str[1], "ue-hans"))
+    {
+      /* Yue Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'z':
+    if (lang_matches (&lang_str[1], "h-hant-hk"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant-mo"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min-nan"))
+    {
+      /* Minnan, Hokkien, Amoy, Taiwanese, Southern Min, Southern Fujian, Hoklo, Southern Fukien, Ho-lo */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hans"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min"))
+    {
+      /* Min, Fuzhou, Hokkien, Amoy, or Taiwanese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+       && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+       && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+       && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  }
+  return false;
+}
+
+/**
+ * hb_ot_ambiguous_tag_to_language
+ * @tag: A language tag.
+ *
+ * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
+ * many language tags) and the best tag is not the alphabetically first, or if
+ * the best tag consists of multiple subtags.
+ *
+ * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
+ * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
+ **/
+static hb_language_t
+hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+{
+  switch (tag)
+  {
+  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
+    return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
+  case HB_TAG('A','R','A',' '):  /* Arabic */
+    return hb_language_from_string ("ar", -1);  /* Arabic */
+  case HB_TAG('A','R','K',' '):  /* Rakhine */
+    return hb_language_from_string ("rki", -1);  /* Rakhine */
+  case HB_TAG('A','T','H',' '):  /* Athapaskan */
+    return hb_language_from_string ("ath", -1);  /* Athapascan */
+  case HB_TAG('B','I','K',' '):  /* Bikol */
+    return hb_language_from_string ("bik", -1);  /* Bikol */
+  case HB_TAG('C','P','P',' '):  /* Creoles */
+    return hb_language_from_string ("crp", -1);  /* Creoles and pidgins */
+  case HB_TAG('C','R','R',' '):  /* Carrier */
+    return hb_language_from_string ("crx", -1);  /* Carrier */
+  case HB_TAG('D','N','K',' '):  /* Dinka */
+    return hb_language_from_string ("din", -1);  /* Dinka */
+  case HB_TAG('D','R','I',' '):  /* Dari */
+    return hb_language_from_string ("prs", -1);  /* Dari */
+  case HB_TAG('D','U','J',' '):  /* Dhuwal */
+    return hb_language_from_string ("dwu", -1);  /* Dhuwal */
+  case HB_TAG('D','Z','N',' '):  /* Dzongkha */
+    return hb_language_from_string ("dz", -1);  /* Dzongkha */
+  case HB_TAG('E','T','I',' '):  /* Estonian */
+    return hb_language_from_string ("et", -1);  /* Estonian */
+  case HB_TAG('G','O','N',' '):  /* Gondi */
+    return hb_language_from_string ("gon", -1);  /* Gondi */
+  case HB_TAG('H','M','N',' '):  /* Hmong */
+    return hb_language_from_string ("hmn", -1);  /* Hmong */
+  case HB_TAG('I','J','O',' '):  /* Ijo */
+    return hb_language_from_string ("ijo", -1);  /* Ijo */
+  case HB_TAG('I','N','U',' '):  /* Inuktitut */
+    return hb_language_from_string ("iu", -1);  /* Inuktitut */
+  case HB_TAG('I','P','K',' '):  /* Inupiat */
+    return hb_language_from_string ("ik", -1);  /* Inupiaq */
+  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+    return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
+  case HB_TAG('I','R','T',' '):  /* Irish Traditional */
+    return hb_language_from_string ("ga-Latg", -1);  /* Irish; Latin (Gaelic variant) */
+  case HB_TAG('J','I','I',' '):  /* Yiddish */
+    return hb_language_from_string ("yi", -1);  /* Yiddish */
+  case HB_TAG('K','A','L',' '):  /* Kalenjin */
+    return hb_language_from_string ("kln", -1);  /* Kalenjin */
+  case HB_TAG('K','G','E',' '):  /* Khutsuri Georgian */
+    return hb_language_from_string ("und-Geok", -1);  /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+  case HB_TAG('K','N','R',' '):  /* Kanuri */
+    return hb_language_from_string ("kr", -1);  /* Kanuri */
+  case HB_TAG('K','O','K',' '):  /* Konkani */
+    return hb_language_from_string ("kok", -1);  /* Konkani */
+  case HB_TAG('K','U','R',' '):  /* Kurdish */
+    return hb_language_from_string ("ku", -1);  /* Kurdish */
+  case HB_TAG('L','U','H',' '):  /* Luyia */
+    return hb_language_from_string ("luy", -1);  /* Luyia */
+  case HB_TAG('L','V','I',' '):  /* Latvian */
+    return hb_language_from_string ("lv", -1);  /* Latvian */
+  case HB_TAG('M','A','W',' '):  /* Marwari */
+    return hb_language_from_string ("mwr", -1);  /* Marwari */
+  case HB_TAG('M','L','G',' '):  /* Malagasy */
+    return hb_language_from_string ("mg", -1);  /* Malagasy */
+  case HB_TAG('M','L','Y',' '):  /* Malay */
+    return hb_language_from_string ("ms", -1);  /* Malay */
+  case HB_TAG('M','N','G',' '):  /* Mongolian */
+    return hb_language_from_string ("mn", -1);  /* Mongolian */
+  case HB_TAG('M','O','L',' '):  /* Moldavian */
+    return hb_language_from_string ("ro-MD", -1);  /* Romanian; Moldova */
+  case HB_TAG('N','E','P',' '):  /* Nepali */
+    return hb_language_from_string ("ne", -1);  /* Nepali */
+  case HB_TAG('N','I','S',' '):  /* Nisi */
+    return hb_language_from_string ("njz", -1);  /* Nyishi */
+  case HB_TAG('N','O','R',' '):  /* Norwegian */
+    return hb_language_from_string ("no", -1);  /* Norwegian */
+  case HB_TAG('O','J','B',' '):  /* Ojibway */
+    return hb_language_from_string ("oj", -1);  /* Ojibwa */
+  case HB_TAG('O','R','O',' '):  /* Oromo */
+    return hb_language_from_string ("om", -1);  /* Oromo */
+  case HB_TAG('P','A','S',' '):  /* Pashto */
+    return hb_language_from_string ("ps", -1);  /* Pashto */
+  case HB_TAG('P','G','R',' '):  /* Polytonic Greek */
+    return hb_language_from_string ("el-polyton", -1);  /* Modern Greek (1453-); Polytonic Greek */
+  case HB_TAG('P','R','O',' '):  /* Provençal / Old Provençal */
+    return hb_language_from_string ("pro", -1);  /* Old Provençal (to 1500) */
+  case HB_TAG('Q','U','H',' '):  /* Quechua (Bolivia) */
+    return hb_language_from_string ("quh", -1);  /* South Bolivian Quechua */
+  case HB_TAG('Q','V','I',' '):  /* Quechua (Ecuador) */
+    return hb_language_from_string ("qvi", -1);  /* Imbabura Highland Quichua */
+  case HB_TAG('Q','W','H',' '):  /* Quechua (Peru) */
+    return hb_language_from_string ("qwh", -1);  /* Huaylas Ancash Quechua */
+  case HB_TAG('R','A','J',' '):  /* Rajasthani */
+    return hb_language_from_string ("raj", -1);  /* Rajasthani */
+  case HB_TAG('R','O','Y',' '):  /* Romany */
+    return hb_language_from_string ("rom", -1);  /* Romany */
+  case HB_TAG('S','Q','I',' '):  /* Albanian */
+    return hb_language_from_string ("sq", -1);  /* Albanian */
+  case HB_TAG('S','Y','R',' '):  /* Syriac */
+    return hb_language_from_string ("syr", -1);  /* Syriac */
+  case HB_TAG('S','Y','R','E'):  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    return hb_language_from_string ("und-Syre", -1);  /* Undetermined; Syriac (Estrangelo variant) */
+  case HB_TAG('S','Y','R','J'):  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    return hb_language_from_string ("und-Syrj", -1);  /* Undetermined; Syriac (Western variant) */
+  case HB_TAG('S','Y','R','N'):  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    return hb_language_from_string ("und-Syrn", -1);  /* Undetermined; Syriac (Eastern variant) */
+  case HB_TAG('T','M','H',' '):  /* Tamashek */
+    return hb_language_from_string ("tmh", -1);  /* Tamashek */
+  case HB_TAG('T','N','E',' '):  /* Tundra Nenets */
+    return hb_language_from_string ("yrk", -1);  /* Nenets */
+  case HB_TAG('Z','H','H',' '):  /* Chinese, Hong Kong SAR */
+    return hb_language_from_string ("zh-HK", -1);  /* Chinese; Hong Kong */
+  case HB_TAG('Z','H','S',' '):  /* Chinese Simplified */
+    return hb_language_from_string ("zh-Hans", -1);  /* Chinese; Han (Simplified variant) */
+  case HB_TAG('Z','H','T',' '):  /* Chinese Traditional */
+    return hb_language_from_string ("zh-Hant", -1);  /* Chinese; Han (Traditional variant) */
+  default:
+    return HB_LANGUAGE_INVALID;
+  }
+}
+
+#endif /* HB_OT_TAG_TABLE_HH */
+
+/* == End of generated table == */
index 991d8e7..d04e532 100644 (file)
@@ -26,7 +26,7 @@
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 /* hb_script_t */
@@ -36,7 +36,8 @@ hb_ot_old_tag_from_script (hb_script_t script)
 {
   /* This seems to be accurate as of end of 2012. */
 
-  switch ((hb_tag_t) script) {
+  switch ((hb_tag_t) script)
+  {
     case HB_SCRIPT_INVALID:            return HB_OT_TAG_DEFAULT_SCRIPT;
 
     /* KATAKANA and HIRAGANA both map to 'kana' */
@@ -49,8 +50,6 @@ hb_ot_old_tag_from_script (hb_script_t script)
     case HB_SCRIPT_NKO:                        return HB_TAG('n','k','o',' ');
     /* Unicode-5.1 additions */
     case HB_SCRIPT_VAI:                        return HB_TAG('v','a','i',' ');
-    /* Unicode-5.2 additions */
-    /* Unicode-6.0 additions */
   }
 
   /* Else, just change first char to lowercase and return */
@@ -114,6 +113,18 @@ hb_ot_new_tag_to_script (hb_tag_t tag)
   return HB_SCRIPT_UNKNOWN;
 }
 
+void
+hb_ot_tags_from_script (hb_script_t  script,
+                       hb_tag_t    *script_tag_1,
+                       hb_tag_t    *script_tag_2)
+{
+  unsigned int count = 2;
+  hb_tag_t tags[2];
+  hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
+  *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
+  *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
+}
+
 /*
  * Complete list at:
  * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
@@ -122,28 +133,37 @@ hb_ot_new_tag_to_script (hb_tag_t tag)
  * So we just do that, and handle the exceptional cases in a switch.
  */
 
-void
-hb_ot_tags_from_script (hb_script_t  script,
-                       hb_tag_t    *script_tag_1,
-                       hb_tag_t    *script_tag_2)
+static void
+hb_ot_all_tags_from_script (hb_script_t   script,
+                           unsigned int *count /* IN/OUT */,
+                           hb_tag_t     *tags /* OUT */)
 {
-  hb_tag_t new_tag;
+  unsigned int i = 0;
 
-  *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT;
-  *script_tag_1 = hb_ot_old_tag_from_script (script);
+  hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
+  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
+  {
+    tags[i++] = new_tag | '3';
+    if (*count > i)
+      tags[i++] = new_tag;
+  }
 
-  new_tag = hb_ot_new_tag_from_script (script);
-  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) {
-    *script_tag_2 = *script_tag_1;
-    *script_tag_1 = new_tag;
+  if (*count > i)
+  {
+    hb_tag_t old_tag = hb_ot_old_tag_from_script (script);
+    if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT)
+      tags[i++] = old_tag;
   }
+
+  *count = i;
 }
 
 hb_script_t
 hb_ot_tag_to_script (hb_tag_t tag)
 {
-  if (unlikely ((tag & 0x000000FFu) == '2'))
-    return hb_ot_new_tag_to_script (tag);
+  unsigned char digit = tag & 0x000000FFu;
+  if (unlikely (digit == '2' || digit == '3'))
+    return hb_ot_new_tag_to_script (tag & 0xFFFFFF32);
 
   return hb_ot_old_tag_to_script (tag);
 }
@@ -151,732 +171,6 @@ hb_ot_tag_to_script (hb_tag_t tag)
 
 /* hb_language_t */
 
-typedef struct {
-  char language[4];
-  hb_tag_t tag;
-} LangTag;
-
-/*
- * Complete list at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- *
- * Generated by intersecting the OpenType language tag list from
- * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
- * 2008-08-04, matching on name, and finally adjusted manually.
- *
- * Updated on 2012-12-07 with more research into remaining codes.
- *
- * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts,
- * the new proposal from Microsoft, and latest ISO 639-3 names.
- *
- * Some items still missing.  Those are commented out at the end.
- * Keep sorted for bsearch.
- *
- * Updated as of 2015-05-06: OT1.7 on MS website has some newer
- * items that we don't have here, eg. Zazaki.  This is the new
- * items in OpenType 1.7 (red items), most of which we have:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- */
-
-static const LangTag ot_languages[] = {
-  {"aa",       HB_TAG('A','F','R',' ')},       /* Afar */
-  {"ab",       HB_TAG('A','B','K',' ')},       /* Abkhazian */
-  {"abq",      HB_TAG('A','B','A',' ')},       /* Abaza */
-  {"acf",      HB_TAG('F','A','N',' ')},       /* French Antillean */
-  {"ach",      HB_TAG('A','C','H',' ')},       /* Acoli */
-  {"acr",      HB_TAG('A','C','R',' ')},       /* Achi */
-  {"ada",      HB_TAG('D','N','G',' ')},       /* Dangme */
-  {"ady",      HB_TAG('A','D','Y',' ')},       /* Adyghe */
-  {"af",       HB_TAG('A','F','K',' ')},       /* Afrikaans */
-  {"ahg",      HB_TAG('A','G','W',' ')},       /* Agaw */
-  {"aii",      HB_TAG('S','W','A',' ')},       /* Swadaya Aramaic */
-  {"aio",      HB_TAG('A','I','O',' ')},       /* Aiton */
-  {"aiw",      HB_TAG('A','R','I',' ')},       /* Aari */
-  {"ak",       HB_TAG('T','W','I',' ')},       /* Akan [macrolanguage] */
-  {"aka",      HB_TAG('A','K','A',' ')},       /* Akan */
-  {"alt",      HB_TAG('A','L','T',' ')},       /* [Southern] Altai */
-  {"am",       HB_TAG('A','M','H',' ')},       /* Amharic */
-  {"amf",      HB_TAG('H','B','N',' ')},       /* Hammer-Banna */
-  {"amw",      HB_TAG('S','Y','R',' ')},       /* Western Neo-Aramaic */
-  {"an",       HB_TAG('A','R','G',' ')},       /* Aragonese */
-  {"ang",      HB_TAG('A','N','G',' ')},       /* Old English (ca. 450-1100) */
-  {"ar",       HB_TAG('A','R','A',' ')},       /* Arabic [macrolanguage] */
-  {"arb",      HB_TAG('A','R','A',' ')},       /* Standard Arabic */
-  {"arn",      HB_TAG('M','A','P',' ')},       /* Mapudungun */
-  {"ary",      HB_TAG('M','O','R',' ')},       /* Moroccan Arabic */
-  {"as",       HB_TAG('A','S','M',' ')},       /* Assamese */
-  {"ast",      HB_TAG('A','S','T',' ')},       /* Asturian/Asturleonese/Bable/Leonese */
-  {"ath",      HB_TAG('A','T','H',' ')},       /* Athapaskan [family] */
-  {"atj",      HB_TAG('R','C','R',' ')},       /* R-Cree */
-  {"atv",      HB_TAG('A','L','T',' ')},       /* [Northern] Altai */
-  {"av",       HB_TAG('A','V','R',' ')},       /* Avaric */
-  {"awa",      HB_TAG('A','W','A',' ')},       /* Awadhi */
-  {"ay",       HB_TAG('A','Y','M',' ')},       /* Aymara [macrolanguage] */
-  {"az",       HB_TAG('A','Z','E',' ')},       /* Azerbaijani [macrolanguage] */
-  {"azb",      HB_TAG('A','Z','B',' ')},       /* South Azerbaijani */
-  {"azj",      HB_TAG('A','Z','E',' ')},       /* North Azerbaijani */
-  {"ba",       HB_TAG('B','S','H',' ')},       /* Bashkir */
-  {"bad",      HB_TAG('B','A','D','0')},       /* Banda */
-  {"bai",      HB_TAG('B','M','L',' ')},       /* Bamileke [family] */
-  {"bal",      HB_TAG('B','L','I',' ')},       /* Baluchi [macrolangauge] */
-  {"ban",      HB_TAG('B','A','N',' ')},       /* Balinese */
-  {"bar",      HB_TAG('B','A','R',' ')},       /* Bavarian */
-  {"bbc",      HB_TAG('B','B','C',' ')},       /* Batak Toba */
-  {"bci",      HB_TAG('B','A','U',' ')},       /* Baoulé */
-  {"bcl",      HB_TAG('B','I','K',' ')},       /* Central Bikol */
-  {"bcq",      HB_TAG('B','C','H',' ')},       /* Bench */
-  {"bdy",      HB_TAG('B','D','Y',' ')},       /* Bandjalang */
-  {"be",       HB_TAG('B','E','L',' ')},       /* Belarusian */
-  {"bem",      HB_TAG('B','E','M',' ')},       /* Bemba (Zambia) */
-  {"ber",      HB_TAG('B','E','R',' ')},       /* Berber [family] */
-  {"bfq",      HB_TAG('B','A','D',' ')},       /* Badaga */
-  {"bft",      HB_TAG('B','L','T',' ')},       /* Balti */
-  {"bfu",      HB_TAG('L','A','H',' ')},       /* Lahuli */
-  {"bfy",      HB_TAG('B','A','G',' ')},       /* Baghelkhandi */
-  {"bg",       HB_TAG('B','G','R',' ')},       /* Bulgarian */
-  {"bgc",      HB_TAG('B','G','C',' ')},       /* Haryanvi */
-  {"bgq",      HB_TAG('B','G','Q',' ')},       /* Bagri */
-  {"bgr",      HB_TAG('Q','I','N',' ')},       /* Bawm Chin */
-  {"bhb",      HB_TAG('B','H','I',' ')},       /* Bhili */
-  {"bhk",      HB_TAG('B','I','K',' ')},       /* Albay Bicolano (retired code) */
-  {"bho",      HB_TAG('B','H','O',' ')},       /* Bhojpuri */
-  {"bi",       HB_TAG('B','I','S',' ')},       /* Bislama */
-  {"bik",      HB_TAG('B','I','K',' ')},       /* Bikol [macrolanguage] */
-  {"bin",      HB_TAG('E','D','O',' ')},       /* Bini */
-  {"bjj",      HB_TAG('B','J','J',' ')},       /* Kanauji */
-  {"bjt",      HB_TAG('B','L','N',' ')},       /* Balanta-Ganja */
-  {"bla",      HB_TAG('B','K','F',' ')},       /* Blackfoot */
-  {"ble",      HB_TAG('B','L','N',' ')},       /* Balanta-Kentohe */
-  {"blk",      HB_TAG('B','L','K',' ')},       /* Pa'O/Pa'o Karen */
-  {"bln",      HB_TAG('B','I','K',' ')},       /* Southern Catanduanes Bikol */
-  {"bm",       HB_TAG('B','M','B',' ')},       /* Bambara */
-  {"bn",       HB_TAG('B','E','N',' ')},       /* Bengali */
-  {"bo",       HB_TAG('T','I','B',' ')},       /* Tibetan */
-  {"bpy",      HB_TAG('B','P','Y',' ')},       /* Bishnupriya */
-  {"bqi",      HB_TAG('L','R','C',' ')},       /* Bakhtiari */
-  {"br",       HB_TAG('B','R','E',' ')},       /* Breton */
-  {"bra",      HB_TAG('B','R','I',' ')},       /* Braj Bhasha */
-  {"brh",      HB_TAG('B','R','H',' ')},       /* Brahui */
-  {"brx",      HB_TAG('B','R','X',' ')},       /* Bodo (India) */
-  {"bs",       HB_TAG('B','O','S',' ')},       /* Bosnian */
-  {"btb",      HB_TAG('B','T','I',' ')},       /* Beti (Cameroon) */
-  {"bto",      HB_TAG('B','I','K',' ')},       /* Rinconada Bikol */
-  {"bts",      HB_TAG('B','T','S',' ')},       /* Batak Simalungun */
-  {"bug",      HB_TAG('B','U','G',' ')},       /* Buginese */
-  {"bxr",      HB_TAG('R','B','U',' ')},       /* Russian Buriat */
-  {"byn",      HB_TAG('B','I','L',' ')},       /* Bilen */
-  {"ca",       HB_TAG('C','A','T',' ')},       /* Catalan */
-  {"cak",      HB_TAG('C','A','K',' ')},       /* Kaqchikel */
-  {"cbk",      HB_TAG('C','B','K',' ')},       /* Chavacano */
-  {"cbl",      HB_TAG('Q','I','N',' ')},       /* Bualkhaw Chin */
-  {"cco",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ce",       HB_TAG('C','H','E',' ')},       /* Chechen */
-  {"ceb",      HB_TAG('C','E','B',' ')},       /* Cebuano */
-  {"cfm",      HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin */
-  {"cgg",      HB_TAG('C','G','G',' ')},       /* Chiga */
-  {"ch",       HB_TAG('C','H','A',' ')},       /* Chamorro */
-  {"chj",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chk",      HB_TAG('C','H','K','0')},       /* Chuukese */
-  {"cho",      HB_TAG('C','H','O',' ')},       /* Choctaw */
-  {"chp",      HB_TAG('C','H','P',' ')},       /* Chipewyan */
-  {"chq",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chr",      HB_TAG('C','H','R',' ')},       /* Cherokee */
-  {"chy",      HB_TAG('C','H','Y',' ')},       /* Cheyenne */
-  {"chz",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cja",      HB_TAG('C','J','A',' ')},       /* Western Cham */
-  {"cjm",      HB_TAG('C','J','M',' ')},       /* Eastern Cham */
-  {"cka",      HB_TAG('Q','I','N',' ')},       /* Khumi Awa Chin */
-  {"ckb",      HB_TAG('K','U','R',' ')},       /* Central Kurdish (Sorani) */
-  {"ckt",      HB_TAG('C','H','K',' ')},       /* Chukchi */
-  {"cld",      HB_TAG('S','Y','R',' ')},       /* Chaldean Neo-Aramaic */
-  {"cle",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cmr",      HB_TAG('Q','I','N',' ')},       /* Mro-Khimi Chin */
-  {"cnb",      HB_TAG('Q','I','N',' ')},       /* Chinbon Chin */
-  {"cnh",      HB_TAG('Q','I','N',' ')},       /* Hakha Chin */
-  {"cnk",      HB_TAG('Q','I','N',' ')},       /* Khumi Chin */
-  {"cnl",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnt",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnw",      HB_TAG('Q','I','N',' ')},       /* Ngawn Chin */
-  {"cop",      HB_TAG('C','O','P',' ')},       /* Coptic */
-  {"cpa",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cpp",      HB_TAG('C','P','P',' ')},       /* Creoles */
-  {"cr",       HB_TAG('C','R','E',' ')},       /* Cree */
-  {"cre",      HB_TAG('Y','C','R',' ')},       /* Y-Cree */
-  {"crh",      HB_TAG('C','R','T',' ')},       /* Crimean Tatar */
-  {"crj",      HB_TAG('E','C','R',' ')},       /* [Southern] East Cree */
-  {"crk",      HB_TAG('W','C','R',' ')},       /* West-Cree */
-  {"crl",      HB_TAG('E','C','R',' ')},       /* [Northern] East Cree */
-  {"crm",      HB_TAG('M','C','R',' ')},       /* Moose Cree */
-  {"crx",      HB_TAG('C','R','R',' ')},       /* Carrier */
-  {"cs",       HB_TAG('C','S','Y',' ')},       /* Czech */
-  {"csa",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csb",      HB_TAG('C','S','B',' ')},       /* Kashubian */
-  {"csh",      HB_TAG('Q','I','N',' ')},       /* Asho Chin */
-  {"cso",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csy",      HB_TAG('Q','I','N',' ')},       /* Siyin Chin */
-  {"ctd",      HB_TAG('Q','I','N',' ')},       /* Tedim Chin */
-  {"cte",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ctg",      HB_TAG('C','T','G',' ')},       /* Chittagonian */
-  {"ctl",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cts",      HB_TAG('B','I','K',' ')},       /* Northern Catanduanes Bikol */
-  {"cu",       HB_TAG('C','S','L',' ')},       /* Church Slavic */
-  {"cuc",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cuk",      HB_TAG('C','U','K',' ')},       /* San Blas Kuna */
-  {"cv",       HB_TAG('C','H','U',' ')},       /* Chuvash */
-  {"cvn",      HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cwd",      HB_TAG('D','C','R',' ')},       /* Woods Cree */
-  {"cy",       HB_TAG('W','E','L',' ')},       /* Welsh */
-  {"czt",      HB_TAG('Q','I','N',' ')},       /* Zotung Chin */
-  {"da",       HB_TAG('D','A','N',' ')},       /* Danish */
-  {"dao",      HB_TAG('Q','I','N',' ')},       /* Daai Chin */
-  {"dap",      HB_TAG('N','I','S',' ')},       /* Nisi (India) */
-  {"dar",      HB_TAG('D','A','R',' ')},       /* Dargwa */
-  {"dax",      HB_TAG('D','A','X',' ')},       /* Dayi */
-  {"de",       HB_TAG('D','E','U',' ')},       /* German */
-  {"dgo",      HB_TAG('D','G','O',' ')},       /* Dogri */
-  {"dhd",      HB_TAG('M','A','W',' ')},       /* Dhundari */
-  {"dhg",      HB_TAG('D','H','G',' ')},       /* Dhangu */
-  {"din",      HB_TAG('D','N','K',' ')},       /* Dinka [macrolanguage] */
-  {"diq",      HB_TAG('D','I','Q',' ')},       /* Dimli */
-  {"dje",      HB_TAG('D','J','R',' ')},       /* Zarma */
-  {"djr",      HB_TAG('D','J','R','0')},       /* Djambarrpuyngu */
-  {"dng",      HB_TAG('D','U','N',' ')},       /* Dungan */
-  {"dnj",      HB_TAG('D','N','J',' ')},       /* Dan */
-  {"doi",      HB_TAG('D','G','R',' ')},       /* Dogri [macrolanguage] */
-  {"dsb",      HB_TAG('L','S','B',' ')},       /* Lower Sorbian */
-  {"duj",      HB_TAG('D','U','J',' ')},       /* Dhuwal */
-  {"dv",       HB_TAG('D','I','V',' ')},       /* Dhivehi/Divehi/Maldivian */
-  {"dyu",      HB_TAG('J','U','L',' ')},       /* Jula */
-  {"dz",       HB_TAG('D','Z','N',' ')},       /* Dzongkha */
-  {"ee",       HB_TAG('E','W','E',' ')},       /* Ewe */
-  {"efi",      HB_TAG('E','F','I',' ')},       /* Efik */
-  {"ekk",      HB_TAG('E','T','I',' ')},       /* Standard Estonian */
-  {"el",       HB_TAG('E','L','L',' ')},       /* Modern Greek (1453-) */
-  {"emk",      HB_TAG('M','N','K',' ')},       /* Eastern Maninkakan */
-  {"en",       HB_TAG('E','N','G',' ')},       /* English */
-  {"enf",      HB_TAG('F','N','E',' ')},       /* Forest Nenets */
-  {"enh",      HB_TAG('T','N','E',' ')},       /* Tundra Nenets */
-  {"eo",       HB_TAG('N','T','O',' ')},       /* Esperanto */
-  {"eot",      HB_TAG('B','T','I',' ')},       /* Beti (Côte d'Ivoire) */
-  {"es",       HB_TAG('E','S','P',' ')},       /* Spanish */
-  {"esu",      HB_TAG('E','S','U',' ')},       /* Central Yupik */
-  {"et",       HB_TAG('E','T','I',' ')},       /* Estonian [macrolanguage] */
-  {"eu",       HB_TAG('E','U','Q',' ')},       /* Basque */
-  {"eve",      HB_TAG('E','V','N',' ')},       /* Even */
-  {"evn",      HB_TAG('E','V','K',' ')},       /* Evenki */
-  {"fa",       HB_TAG('F','A','R',' ')},       /* Persian [macrolanguage] */
-  {"fan",      HB_TAG('F','A','N','0')},       /* Fang */
-  {"fat",      HB_TAG('F','A','T',' ')},       /* Fanti */
-  {"ff",       HB_TAG('F','U','L',' ')},       /* Fulah [macrolanguage] */
-  {"fi",       HB_TAG('F','I','N',' ')},       /* Finnish */
-  {"fil",      HB_TAG('P','I','L',' ')},       /* Filipino */
-  {"fj",       HB_TAG('F','J','I',' ')},       /* Fijian */
-  {"flm",      HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin [retired ISO639 code] */
-  {"fo",       HB_TAG('F','O','S',' ')},       /* Faroese */
-  {"fon",      HB_TAG('F','O','N',' ')},       /* Fon */
-  {"fr",       HB_TAG('F','R','A',' ')},       /* French */
-  {"frc",      HB_TAG('F','R','C',' ')},       /* Cajun French */
-  {"frp",      HB_TAG('F','R','P',' ')},       /* Arpitan/Francoprovençal */
-  {"fuf",      HB_TAG('F','T','A',' ')},       /* Futa */
-  {"fur",      HB_TAG('F','R','L',' ')},       /* Friulian */
-  {"fuv",      HB_TAG('F','U','V',' ')},       /* Nigerian Fulfulde */
-  {"fy",       HB_TAG('F','R','I',' ')},       /* Western Frisian */
-  {"ga",       HB_TAG('I','R','I',' ')},       /* Irish */
-  {"gaa",      HB_TAG('G','A','D',' ')},       /* Ga */
-  {"gag",      HB_TAG('G','A','G',' ')},       /* Gagauz */
-  {"gbm",      HB_TAG('G','A','W',' ')},       /* Garhwali */
-  {"gd",       HB_TAG('G','A','E',' ')},       /* Scottish Gaelic */
-  {"gez",      HB_TAG('G','E','Z',' ')},       /* Ge'ez */
-  {"ggo",      HB_TAG('G','O','N',' ')},       /* Southern Gondi */
-  {"gih",      HB_TAG('G','I','H',' ')},       /* Githabul */
-  {"gil",      HB_TAG('G','I','L','0')},       /* Kiribati (Gilbertese) */
-  {"gkp",      HB_TAG('G','K','P',' ')},       /* Kpelle (Guinea) */
-  {"gl",       HB_TAG('G','A','L',' ')},       /* Galician */
-  {"gld",      HB_TAG('N','A','N',' ')},       /* Nanai */
-  {"glk",      HB_TAG('G','L','K',' ')},       /* Gilaki */
-  {"gn",       HB_TAG('G','U','A',' ')},       /* Guarani [macrolanguage] */
-  {"gnn",      HB_TAG('G','N','N',' ')},       /* Gumatj */
-  {"gno",      HB_TAG('G','O','N',' ')},       /* Northern Gondi */
-  {"gog",      HB_TAG('G','O','G',' ')},       /* Gogo */
-  {"gon",      HB_TAG('G','O','N',' ')},       /* Gondi [macrolanguage] */
-  {"grt",      HB_TAG('G','R','O',' ')},       /* Garo */
-  {"gru",      HB_TAG('S','O','G',' ')},       /* Sodo Gurage */
-  {"gsw",      HB_TAG('A','L','S',' ')},       /* Alsatian */
-  {"gu",       HB_TAG('G','U','J',' ')},       /* Gujarati */
-  {"guc",      HB_TAG('G','U','C',' ')},       /* Wayuu */
-  {"guf",      HB_TAG('G','U','F',' ')},       /* Gupapuyngu */
-  {"guk",      HB_TAG('G','M','Z',' ')},       /* Gumuz */
-/*{"guk",      HB_TAG('G','U','K',' ')},*/     /* Gumuz (in SIL fonts) */
-  {"guz",      HB_TAG('G','U','Z',' ')},       /* Ekegusii/Gusii */
-  {"gv",       HB_TAG('M','N','X',' ')},       /* Manx */
-  {"ha",       HB_TAG('H','A','U',' ')},       /* Hausa */
-  {"har",      HB_TAG('H','R','I',' ')},       /* Harari */
-  {"haw",      HB_TAG('H','A','W',' ')},       /* Hawaiian */
-  {"hay",      HB_TAG('H','A','Y',' ')},       /* Haya */
-  {"haz",      HB_TAG('H','A','Z',' ')},       /* Hazaragi */
-  {"he",       HB_TAG('I','W','R',' ')},       /* Hebrew */
-  {"hi",       HB_TAG('H','I','N',' ')},       /* Hindi */
-  {"hil",      HB_TAG('H','I','L',' ')},       /* Hiligaynon */
-  {"hlt",      HB_TAG('Q','I','N',' ')},       /* Matu Chin */
-  {"hmn",      HB_TAG('H','M','N',' ')},       /* Hmong */
-  {"hnd",      HB_TAG('H','N','D',' ')},       /* [Southern] Hindko */
-  {"hne",      HB_TAG('C','H','H',' ')},       /* Chattisgarhi */
-  {"hno",      HB_TAG('H','N','D',' ')},       /* [Northern] Hindko */
-  {"ho",       HB_TAG('H','M','O',' ')},       /* Hiri Motu */
-  {"hoc",      HB_TAG('H','O',' ',' ')},       /* Ho */
-  {"hoj",      HB_TAG('H','A','R',' ')},       /* Harauti */
-  {"hr",       HB_TAG('H','R','V',' ')},       /* Croatian */
-  {"hsb",      HB_TAG('U','S','B',' ')},       /* Upper Sorbian */
-  {"ht",       HB_TAG('H','A','I',' ')},       /* Haitian/Haitian Creole */
-  {"hu",       HB_TAG('H','U','N',' ')},       /* Hungarian */
-  {"hy",       HB_TAG('H','Y','E',' ')},       /* Armenian */
-  {"hz",       HB_TAG('H','E','R',' ')},       /* Herero */
-  {"ia",       HB_TAG('I','N','A',' ')},       /* Interlingua (International Auxiliary Language Association) */
-  {"iba",      HB_TAG('I','B','A',' ')},       /* Iban */
-  {"ibb",      HB_TAG('I','B','B',' ')},       /* Ibibio */
-  {"id",       HB_TAG('I','N','D',' ')},       /* Indonesian */
-  {"ie",       HB_TAG('I','L','E',' ')},       /* Interlingue/Occidental */
-  {"ig",       HB_TAG('I','B','O',' ')},       /* Igbo */
-  {"igb",      HB_TAG('E','B','I',' ')},       /* Ebira */
-  {"ii",       HB_TAG('Y','I','M',' ')},       /* Yi Modern */
-  {"ijc",      HB_TAG('I','J','O',' ')},       /* Izon */
-  {"ijo",      HB_TAG('I','J','O',' ')},       /* Ijo [family] */
-  {"ik",       HB_TAG('I','P','K',' ')},       /* Inupiaq [macrolanguage] */
-  {"ilo",      HB_TAG('I','L','O',' ')},       /* Ilokano */
-  {"inh",      HB_TAG('I','N','G',' ')},       /* Ingush */
-  {"io",       HB_TAG('I','D','O',' ')},       /* Ido */
-  {"is",       HB_TAG('I','S','L',' ')},       /* Icelandic */
-  {"it",       HB_TAG('I','T','A',' ')},       /* Italian */
-  {"iu",       HB_TAG('I','N','U',' ')},       /* Inuktitut [macrolanguage] */
-  {"ja",       HB_TAG('J','A','N',' ')},       /* Japanese */
-  {"jam",      HB_TAG('J','A','M',' ')},       /* Jamaican Creole English */
-  {"jbo",      HB_TAG('J','B','O',' ')},       /* Lojban */
-  {"jv",       HB_TAG('J','A','V',' ')},       /* Javanese */
-  {"ka",       HB_TAG('K','A','T',' ')},       /* Georgian */
-  {"kaa",      HB_TAG('K','R','K',' ')},       /* Karakalpak */
-  {"kab",      HB_TAG('K','A','B','0')},       /* Kabyle */
-  {"kam",      HB_TAG('K','M','B',' ')},       /* Kamba (Kenya) */
-  {"kar",      HB_TAG('K','R','N',' ')},       /* Karen [family] */
-  {"kat",      HB_TAG('K','G','E',' ')},       /* Khutsuri Georgian */
-  {"kbd",      HB_TAG('K','A','B',' ')},       /* Kabardian */
-  {"kde",      HB_TAG('K','D','E',' ')},       /* Makonde */
-  {"kdr",      HB_TAG('K','R','M',' ')},       /* Karaim */
-  {"kdt",      HB_TAG('K','U','Y',' ')},       /* Kuy */
-  {"kea",      HB_TAG('K','E','A',' ')},       /* Kabuverdianu (Crioulo) */
-  {"kek",      HB_TAG('K','E','K',' ')},       /* Kekchi */
-  {"kex",      HB_TAG('K','K','N',' ')},       /* Kokni */
-  {"kfa",      HB_TAG('K','O','D',' ')},       /* Kodagu */
-  {"kfr",      HB_TAG('K','A','C',' ')},       /* Kachchi */
-  {"kfx",      HB_TAG('K','U','L',' ')},       /* Kulvi */
-  {"kfy",      HB_TAG('K','M','N',' ')},       /* Kumaoni */
-  {"kg",       HB_TAG('K','O','N',' ')},       /* Kongo [macrolanguage] */
-  {"kha",      HB_TAG('K','S','I',' ')},       /* Khasi */
-  {"khb",      HB_TAG('X','B','D',' ')},       /* Lü */
-  {"kht",      HB_TAG('K','H','N',' ')},       /* Khamti (Microsoft fonts) */
-/*{"kht",      HB_TAG('K','H','T',' ')},*/     /* Khamti (OpenType spec and SIL fonts) */
-  {"khw",      HB_TAG('K','H','W',' ')},       /* Khowar */
-  {"ki",       HB_TAG('K','I','K',' ')},       /* Gikuyu/Kikuyu */
-  {"kiu",      HB_TAG('K','I','U',' ')},       /* Kirmanjki */
-  {"kj",       HB_TAG('K','U','A',' ')},       /* Kuanyama/Kwanyama */
-  {"kjd",      HB_TAG('K','J','D',' ')},       /* Southern Kiwai */
-  {"kjh",      HB_TAG('K','H','A',' ')},       /* Khakass */
-  {"kjp",      HB_TAG('K','J','P',' ')},       /* Pwo Eastern Karen */
-  {"kk",       HB_TAG('K','A','Z',' ')},       /* Kazakh */
-  {"kl",       HB_TAG('G','R','N',' ')},       /* Kalaallisut */
-  {"kln",      HB_TAG('K','A','L',' ')},       /* Kalenjin */
-  {"km",       HB_TAG('K','H','M',' ')},       /* Central Khmer */
-  {"kmb",      HB_TAG('M','B','N',' ')},       /* Kimbundu */
-  {"kmw",      HB_TAG('K','M','O',' ')},       /* Komo (Democratic Republic of Congo) */
-  {"kn",       HB_TAG('K','A','N',' ')},       /* Kannada */
-  {"knn",      HB_TAG('K','O','K',' ')},       /* Konkani */
-  {"ko",       HB_TAG('K','O','R',' ')},       /* Korean */
-  {"koi",      HB_TAG('K','O','P',' ')},       /* Komi-Permyak */
-  {"kok",      HB_TAG('K','O','K',' ')},       /* Konkani [macrolanguage] */
-  {"kon",      HB_TAG('K','O','N','0')},       /* Kongo */
-  {"kos",      HB_TAG('K','O','S',' ')},       /* Kosraean */
-  {"kpe",      HB_TAG('K','P','L',' ')},       /* Kpelle [macrolanguage] */
-  {"kpv",      HB_TAG('K','O','Z',' ')},       /* Komi-Zyrian */
-  {"kpy",      HB_TAG('K','Y','K',' ')},       /* Koryak */
-  {"kqy",      HB_TAG('K','R','T',' ')},       /* Koorete */
-  {"kr",       HB_TAG('K','N','R',' ')},       /* Kanuri [macrolanguage] */
-  {"kri",      HB_TAG('K','R','I',' ')},       /* Krio */
-  {"krl",      HB_TAG('K','R','L',' ')},       /* Karelian */
-  {"kru",      HB_TAG('K','U','U',' ')},       /* Kurukh */
-  {"ks",       HB_TAG('K','S','H',' ')},       /* Kashmiri */
-  {"ksh",      HB_TAG('K','S','H','0')},       /* Ripuarian, Kölsch */
-/*{"ksw",      HB_TAG('K','R','N',' ')},*/     /* S'gaw Karen (Microsoft fonts?) */
-  {"ksw",      HB_TAG('K','S','W',' ')},       /* S'gaw Karen (OpenType spec and SIL fonts) */
-  {"ktb",      HB_TAG('K','E','B',' ')},       /* Kebena */
-  {"ktu",      HB_TAG('K','O','N',' ')},       /* Kikongo */
-  {"ku",       HB_TAG('K','U','R',' ')},       /* Kurdish [macrolanguage] */
-  {"kum",      HB_TAG('K','U','M',' ')},       /* Kumyk */
-  {"kv",       HB_TAG('K','O','M',' ')},       /* Komi [macrolanguage] */
-  {"kvd",      HB_TAG('K','U','I',' ')},       /* Kui (Indonesia) */
-  {"kw",       HB_TAG('C','O','R',' ')},       /* Cornish */
-  {"kxc",      HB_TAG('K','M','S',' ')},       /* Komso */
-  {"kxu",      HB_TAG('K','U','I',' ')},       /* Kui (India) */
-  {"ky",       HB_TAG('K','I','R',' ')},       /* Kirghiz/Kyrgyz */
-  {"kyu",      HB_TAG('K','Y','U',' ')},       /* Western Kayah */
-  {"la",       HB_TAG('L','A','T',' ')},       /* Latin */
-  {"lad",      HB_TAG('J','U','D',' ')},       /* Ladino */
-  {"lb",       HB_TAG('L','T','Z',' ')},       /* Luxembourgish */
-  {"lbe",      HB_TAG('L','A','K',' ')},       /* Lak */
-  {"lbj",      HB_TAG('L','D','K',' ')},       /* Ladakhi */
-  {"lez",      HB_TAG('L','E','Z',' ')},       /* Lezgi */
-  {"lg",       HB_TAG('L','U','G',' ')},       /* Ganda */
-  {"li",       HB_TAG('L','I','M',' ')},       /* Limburgan/Limburger/Limburgish */
-  {"lif",      HB_TAG('L','M','B',' ')},       /* Limbu */
-  {"lij",      HB_TAG('L','I','J',' ')},       /* Ligurian */
-  {"lis",      HB_TAG('L','I','S',' ')},       /* Lisu */
-  {"ljp",      HB_TAG('L','J','P',' ')},       /* Lampung Api */
-  {"lki",      HB_TAG('L','K','I',' ')},       /* Laki */
-  {"lld",      HB_TAG('L','A','D',' ')},       /* Ladin */
-  {"lmn",      HB_TAG('L','A','M',' ')},       /* Lambani */
-  {"lmo",      HB_TAG('L','M','O',' ')},       /* Lombard */
-  {"ln",       HB_TAG('L','I','N',' ')},       /* Lingala */
-  {"lo",       HB_TAG('L','A','O',' ')},       /* Lao */
-  {"lom",      HB_TAG('L','O','M',' ')},       /* Loma */
-  {"lrc",      HB_TAG('L','R','C',' ')},       /* Northern Luri */
-  {"lt",       HB_TAG('L','T','H',' ')},       /* Lithuanian */
-  {"lu",       HB_TAG('L','U','B',' ')},       /* Luba-Katanga */
-  {"lua",      HB_TAG('L','U','B',' ')},       /* Luba-Kasai */
-  {"luo",      HB_TAG('L','U','O',' ')},       /* Luo (Kenya and Tanzania) */
-  {"lus",      HB_TAG('M','I','Z',' ')},       /* Mizo */
-  {"luy",      HB_TAG('L','U','H',' ')},       /* Luyia/Oluluyia [macrolanguage] */
-  {"luz",      HB_TAG('L','R','C',' ')},       /* Southern Luri */
-  {"lv",       HB_TAG('L','V','I',' ')},       /* Latvian */
-  {"lzz",      HB_TAG('L','A','Z',' ')},       /* Laz */
-  {"mad",      HB_TAG('M','A','D',' ')},       /* Madurese */
-  {"mag",      HB_TAG('M','A','G',' ')},       /* Magahi */
-  {"mai",      HB_TAG('M','T','H',' ')},       /* Maithili */
-  {"mak",      HB_TAG('M','K','R',' ')},       /* Makasar */
-  {"mam",      HB_TAG('M','A','M',' ')},       /* Mam */
-  {"man",      HB_TAG('M','N','K',' ')},       /* Manding/Mandingo [macrolanguage] */
-  {"mdc",      HB_TAG('M','L','E',' ')},       /* Male (Papua New Guinea) */
-  {"mdf",      HB_TAG('M','O','K',' ')},       /* Moksha */
-  {"mdr",      HB_TAG('M','D','R',' ')},       /* Mandar */
-  {"mdy",      HB_TAG('M','L','E',' ')},       /* Male (Ethiopia) */
-  {"men",      HB_TAG('M','D','E',' ')},       /* Mende (Sierra Leone) */
-  {"mer",      HB_TAG('M','E','R',' ')},       /* Meru */
-  {"mfe",      HB_TAG('M','F','E',' ')},       /* Morisyen */
-  {"mg",       HB_TAG('M','L','G',' ')},       /* Malagasy [macrolanguage] */
-  {"mh",       HB_TAG('M','A','H',' ')},       /* Marshallese */
-  {"mhr",      HB_TAG('L','M','A',' ')},       /* Low Mari */
-  {"mi",       HB_TAG('M','R','I',' ')},       /* Maori */
-  {"min",      HB_TAG('M','I','N',' ')},       /* Minangkabau */
-  {"mk",       HB_TAG('M','K','D',' ')},       /* Macedonian */
-  {"mku",      HB_TAG('M','N','K',' ')},       /* Konyanka Maninka */
-  {"mkw",      HB_TAG('M','K','W',' ')},       /* Kituba (Congo) */
-  {"ml",       HB_TAG('M','L','R',' ')},       /* Malayalam */
-  {"mlq",      HB_TAG('M','N','K',' ')},       /* Western Maninkakan */
-  {"mn",       HB_TAG('M','N','G',' ')},       /* Mongolian [macrolanguage] */
-  {"mnc",      HB_TAG('M','C','H',' ')},       /* Manchu */
-  {"mni",      HB_TAG('M','N','I',' ')},       /* Manipuri */
-  {"mnk",      HB_TAG('M','N','D',' ')},       /* Mandinka */
-  {"mns",      HB_TAG('M','A','N',' ')},       /* Mansi */
-  {"mnw",      HB_TAG('M','O','N',' ')},       /* Mon */
-  {"mo",       HB_TAG('M','O','L',' ')},       /* Moldavian */
-  {"moh",      HB_TAG('M','O','H',' ')},       /* Mohawk */
-  {"mos",      HB_TAG('M','O','S',' ')},       /* Mossi */
-  {"mpe",      HB_TAG('M','A','J',' ')},       /* Majang */
-  {"mr",       HB_TAG('M','A','R',' ')},       /* Marathi */
-  {"mrh",      HB_TAG('Q','I','N',' ')},       /* Mara Chin */
-  {"mrj",      HB_TAG('H','M','A',' ')},       /* High Mari */
-  {"ms",       HB_TAG('M','L','Y',' ')},       /* Malay [macrolanguage] */
-  {"msc",      HB_TAG('M','N','K',' ')},       /* Sankaran Maninka */
-  {"mt",       HB_TAG('M','T','S',' ')},       /* Maltese */
-  {"mtr",      HB_TAG('M','A','W',' ')},       /* Mewari */
-  {"mus",      HB_TAG('M','U','S',' ')},       /* Creek */
-  {"mve",      HB_TAG('M','A','W',' ')},       /* Marwari (Pakistan) */
-  {"mwk",      HB_TAG('M','N','K',' ')},       /* Kita Maninkakan */
-  {"mwl",      HB_TAG('M','W','L',' ')},       /* Mirandese */
-  {"mwr",      HB_TAG('M','A','W',' ')},       /* Marwari [macrolanguage] */
-  {"mww",      HB_TAG('M','W','W',' ')},       /* Hmong Daw */
-  {"my",       HB_TAG('B','R','M',' ')},       /* Burmese */
-  {"mym",      HB_TAG('M','E','N',' ')},       /* Me'en */
-  {"myn",      HB_TAG('M','Y','N',' ')},       /* Mayan */
-  {"myq",      HB_TAG('M','N','K',' ')},       /* Forest Maninka (retired code) */
-  {"myv",      HB_TAG('E','R','Z',' ')},       /* Erzya */
-  {"mzn",      HB_TAG('M','Z','N',' ')},       /* Mazanderani */
-  {"na",       HB_TAG('N','A','U',' ')},       /* Nauru */
-  {"nag",      HB_TAG('N','A','G',' ')},       /* Naga-Assamese */
-  {"nah",      HB_TAG('N','A','H',' ')},       /* Nahuatl [family] */
-  {"nap",      HB_TAG('N','A','P',' ')},       /* Neapolitan */
-  {"nb",       HB_TAG('N','O','R',' ')},       /* Norwegian Bokmål */
-  {"nco",      HB_TAG('S','I','B',' ')},       /* Sibe */
-  {"nd",       HB_TAG('N','D','B',' ')},       /* [North] Ndebele */
-  {"ndc",      HB_TAG('N','D','C',' ')},       /* Ndau */
-  {"nds",      HB_TAG('N','D','S',' ')},       /* Low German/Low Saxon */
-  {"ne",       HB_TAG('N','E','P',' ')},       /* Nepali */
-  {"new",      HB_TAG('N','E','W',' ')},       /* Newari */
-  {"ng",       HB_TAG('N','D','G',' ')},       /* Ndonga */
-  {"nga",      HB_TAG('N','G','A',' ')},       /* Ngabaka */
-  {"ngl",      HB_TAG('L','M','W',' ')},       /* Lomwe */
-  {"ngo",      HB_TAG('S','X','T',' ')},       /* Sutu */
-  {"niu",      HB_TAG('N','I','U',' ')},       /* Niuean */
-  {"niv",      HB_TAG('G','I','L',' ')},       /* Gilyak */
-  {"nl",       HB_TAG('N','L','D',' ')},       /* Dutch */
-  {"nn",       HB_TAG('N','Y','N',' ')},       /* Norwegian Nynorsk */
-  {"no",       HB_TAG('N','O','R',' ')},       /* Norwegian [macrolanguage] */
-  {"nod",      HB_TAG('N','T','A',' ')},       /* Northern Thai */
-  {"noe",      HB_TAG('N','O','E',' ')},       /* Nimadi */
-  {"nog",      HB_TAG('N','O','G',' ')},       /* Nogai */
-  {"nov",      HB_TAG('N','O','V',' ')},       /* Novial */
-  {"nqo",      HB_TAG('N','K','O',' ')},       /* N'Ko */
-  {"nr",       HB_TAG('N','D','B',' ')},       /* [South] Ndebele */
-  {"nsk",      HB_TAG('N','A','S',' ')},       /* Naskapi */
-  {"nso",      HB_TAG('S','O','T',' ')},       /* [Northern] Sotho */
-  {"nv",       HB_TAG('N','A','V',' ')},       /* Navajo */
-  {"ny",       HB_TAG('C','H','I',' ')},       /* Chewa/Chichwa/Nyanja */
-  {"nym",      HB_TAG('N','Y','M',' ')},       /* Nyamwezi */
-  {"nyn",      HB_TAG('N','K','L',' ')},       /* Nyankole */
-  {"oc",       HB_TAG('O','C','I',' ')},       /* Occitan (post 1500) */
-  {"oj",       HB_TAG('O','J','B',' ')},       /* Ojibwa [macrolanguage] */
-  {"ojs",      HB_TAG('O','C','R',' ')},       /* Oji-Cree */
-  {"okm",      HB_TAG('K','O','H',' ')},       /* Korean Old Hangul */
-  {"om",       HB_TAG('O','R','O',' ')},       /* Oromo [macrolanguage] */
-  {"or",       HB_TAG('O','R','I',' ')},       /* Oriya */
-  {"os",       HB_TAG('O','S','S',' ')},       /* Ossetian */
-  {"pa",       HB_TAG('P','A','N',' ')},       /* Panjabi */
-  {"pag",      HB_TAG('P','A','G',' ')},       /* Pangasinan */
-  {"pam",      HB_TAG('P','A','M',' ')},       /* Kapampangan/Pampanga */
-  {"pap",      HB_TAG('P','A','P','0')},       /* Papiamento */
-  {"pau",      HB_TAG('P','A','U',' ')},       /* Palauan */
-  {"pcc",      HB_TAG('P','C','C',' ')},       /* Bouyei */
-  {"pcd",      HB_TAG('P','C','D',' ')},       /* Picard */
-  {"pce",      HB_TAG('P','L','G',' ')},       /* [Ruching] Palaung */
-  {"pck",      HB_TAG('Q','I','N',' ')},       /* Paite Chin */
-  {"pdc",      HB_TAG('P','D','C',' ')},       /* Pennsylvania German */
-  {"pes",      HB_TAG('F','A','R',' ')},       /* Iranian Persian */
-  {"phk",      HB_TAG('P','H','K',' ')},       /* Phake */
-  {"pi",       HB_TAG('P','A','L',' ')},       /* Pali */
-  {"pih",      HB_TAG('P','I','H',' ')},       /* Pitcairn-Norfolk */
-  {"pl",       HB_TAG('P','L','K',' ')},       /* Polish */
-  {"pll",      HB_TAG('P','L','G',' ')},       /* [Shwe] Palaung */
-  {"plp",      HB_TAG('P','A','P',' ')},       /* Palpa */
-  {"pms",      HB_TAG('P','M','S',' ')},       /* Piemontese */
-  {"pnb",      HB_TAG('P','N','B',' ')},       /* Western Panjabi */
-  {"poh",      HB_TAG('P','O','H',' ')},       /* Pocomchi */
-  {"pon",      HB_TAG('P','O','N',' ')},       /* Pohnpeian */
-  {"prs",      HB_TAG('D','R','I',' ')},       /* Afghan Persian/Dari */
-  {"ps",       HB_TAG('P','A','S',' ')},       /* Pashto/Pushto [macrolanguage] */
-  {"pt",       HB_TAG('P','T','G',' ')},       /* Portuguese */
-  {"pwo",      HB_TAG('P','W','O',' ')},       /* Pwo Western Karen */
-  {"qu",       HB_TAG('Q','U','Z',' ')},       /* Quechua [macrolanguage] */
-  {"quc",      HB_TAG('Q','U','C',' ')},       /* K'iche'/Quiché */
-  {"quh",      HB_TAG('Q','U','H',' ')},       /* Quechua (Bolivia) */
-  {"quz",      HB_TAG('Q','U','Z',' ')},       /* Cusco Quechua */
-  {"qvi",      HB_TAG('Q','V','I',' ')},       /* Quechua (Ecuador) */
-  {"qwh",      HB_TAG('Q','W','H',' ')},       /* Quechua (Peru) */
-  {"raj",      HB_TAG('R','A','J',' ')},       /* Rajasthani [macrolanguage] */
-  {"rar",      HB_TAG('R','A','R',' ')},       /* Rarotongan */
-  {"rbb",      HB_TAG('P','L','G',' ')},       /* Rumai Palaung */
-  {"rej",      HB_TAG('R','E','J',' ')},       /* Rejang */
-  {"ria",      HB_TAG('R','I','A',' ')},       /* Riang (India) */
-  {"rif",      HB_TAG('R','I','F',' ')},       /* Tarifit */
-  {"ril",      HB_TAG('R','I','A',' ')},       /* Riang (Myanmar) */
-  {"rit",      HB_TAG('R','I','T',' ')},       /* Ritarungo */
-  {"rki",      HB_TAG('A','R','K',' ')},       /* Rakhine */
-  {"rkw",      HB_TAG('R','K','W',' ')},       /* Arakwal */
-  {"rm",       HB_TAG('R','M','S',' ')},       /* Romansh */
-  {"rmy",      HB_TAG('R','M','Y',' ')},       /* Vlax Romani */
-  {"rn",       HB_TAG('R','U','N',' ')},       /* Rundi */
-  {"ro",       HB_TAG('R','O','M',' ')},       /* Romanian */
-  {"rom",      HB_TAG('R','O','Y',' ')},       /* Romany [macrolanguage] */
-  {"rtm",      HB_TAG('R','T','M',' ')},       /* Rotuman */
-  {"ru",       HB_TAG('R','U','S',' ')},       /* Russian */
-  {"rue",      HB_TAG('R','S','Y',' ')},       /* Rusyn */
-  {"rup",      HB_TAG('R','U','P',' ')},       /* Aromanian/Arumanian/Macedo-Romanian */
-  {"rw",       HB_TAG('R','U','A',' ')},       /* Kinyarwanda */
-  {"rwr",      HB_TAG('M','A','W',' ')},       /* Marwari (India) */
-  {"sa",       HB_TAG('S','A','N',' ')},       /* Sanskrit */
-  {"sah",      HB_TAG('Y','A','K',' ')},       /* Yakut */
-  {"sam",      HB_TAG('P','A','A',' ')},       /* Palestinian Aramaic */
-  {"sas",      HB_TAG('S','A','S',' ')},       /* Sasak */
-  {"sat",      HB_TAG('S','A','T',' ')},       /* Santali */
-  {"sc",       HB_TAG('S','R','D',' ')},       /* Sardinian [macrolanguage] */
-  {"sck",      HB_TAG('S','A','D',' ')},       /* Sadri */
-  {"scn",      HB_TAG('S','C','N',' ')},       /* Sicilian */
-  {"sco",      HB_TAG('S','C','O',' ')},       /* Scots */
-  {"scs",      HB_TAG('S','L','A',' ')},       /* [North] Slavey */
-  {"sd",       HB_TAG('S','N','D',' ')},       /* Sindhi */
-  {"se",       HB_TAG('N','S','M',' ')},       /* Northern Sami */
-  {"seh",      HB_TAG('S','N','A',' ')},       /* Sena */
-  {"sel",      HB_TAG('S','E','L',' ')},       /* Selkup */
-  {"sez",      HB_TAG('Q','I','N',' ')},       /* Senthang Chin */
-  {"sg",       HB_TAG('S','G','O',' ')},       /* Sango */
-  {"sga",      HB_TAG('S','G','A',' ')},       /* Old Irish (to 900) */
-  {"sgs",      HB_TAG('S','G','S',' ')},       /* Samogitian */
-  {"sgw",      HB_TAG('C','H','G',' ')},       /* Sebat Bet Gurage */
-/*{"sgw",      HB_TAG('S','G','W',' ')},*/     /* Sebat Bet Gurage (in SIL fonts) */
-  {"shi",      HB_TAG('S','H','I',' ')},       /* Tachelhit */
-  {"shn",      HB_TAG('S','H','N',' ')},       /* Shan */
-  {"si",       HB_TAG('S','N','H',' ')},       /* Sinhala */
-  {"sid",      HB_TAG('S','I','D',' ')},       /* Sidamo */
-  {"sjd",      HB_TAG('K','S','M',' ')},       /* Kildin Sami */
-  {"sk",       HB_TAG('S','K','Y',' ')},       /* Slovak */
-  {"skr",      HB_TAG('S','R','K',' ')},       /* Seraiki */
-  {"sl",       HB_TAG('S','L','V',' ')},       /* Slovenian */
-  {"sm",       HB_TAG('S','M','O',' ')},       /* Samoan */
-  {"sma",      HB_TAG('S','S','M',' ')},       /* Southern Sami */
-  {"smj",      HB_TAG('L','S','M',' ')},       /* Lule Sami */
-  {"smn",      HB_TAG('I','S','M',' ')},       /* Inari Sami */
-  {"sms",      HB_TAG('S','K','S',' ')},       /* Skolt Sami */
-  {"sn",       HB_TAG('S','N','A','0')},       /* Shona */
-  {"snk",      HB_TAG('S','N','K',' ')},       /* Soninke */
-  {"so",       HB_TAG('S','M','L',' ')},       /* Somali */
-  {"sop",      HB_TAG('S','O','P',' ')},       /* Songe */
-  {"sq",       HB_TAG('S','Q','I',' ')},       /* Albanian [macrolanguage] */
-  {"sr",       HB_TAG('S','R','B',' ')},       /* Serbian */
-  {"srr",      HB_TAG('S','R','R',' ')},       /* Serer */
-  {"ss",       HB_TAG('S','W','Z',' ')},       /* Swati */
-  {"st",       HB_TAG('S','O','T',' ')},       /* [Southern] Sotho */
-  {"stq",      HB_TAG('S','T','Q',' ')},       /* Saterfriesisch */
-  {"stv",      HB_TAG('S','I','G',' ')},       /* Silt'e */
-  {"su",       HB_TAG('S','U','N',' ')},       /* Sundanese */
-  {"suk",      HB_TAG('S','U','K',' ')},       /* Sukama */
-  {"suq",      HB_TAG('S','U','R',' ')},       /* Suri */
-  {"sv",       HB_TAG('S','V','E',' ')},       /* Swedish */
-  {"sva",      HB_TAG('S','V','A',' ')},       /* Svan */
-  {"sw",       HB_TAG('S','W','K',' ')},       /* Swahili [macrolanguage] */
-  {"swb",      HB_TAG('C','M','R',' ')},       /* Comorian */
-  {"swh",      HB_TAG('S','W','K',' ')},       /* Kiswahili/Swahili */
-  {"swv",      HB_TAG('M','A','W',' ')},       /* Shekhawati */
-  {"sxu",      HB_TAG('S','X','U',' ')},       /* Upper Saxon */
-  {"syc",      HB_TAG('S','Y','R',' ')},       /* Classical Syriac */
-  {"syl",      HB_TAG('S','Y','L',' ')},       /* Sylheti */
-  {"syr",      HB_TAG('S','Y','R',' ')},       /* Syriac [macrolanguage] */
-  {"szl",      HB_TAG('S','Z','L',' ')},       /* Silesian */
-  {"ta",       HB_TAG('T','A','M',' ')},       /* Tamil */
-  {"tab",      HB_TAG('T','A','B',' ')},       /* Tabasaran */
-  {"tcp",      HB_TAG('Q','I','N',' ')},       /* Tawr Chin */
-  {"tcy",      HB_TAG('T','U','L',' ')},       /* Tulu */
-  {"tcz",      HB_TAG('Q','I','N',' ')},       /* Thado Chin */
-  {"tdd",      HB_TAG('T','D','D',' ')},       /* Tai Nüa */
-  {"te",       HB_TAG('T','E','L',' ')},       /* Telugu */
-  {"tem",      HB_TAG('T','M','N',' ')},       /* Temne */
-  {"tet",      HB_TAG('T','E','T',' ')},       /* Tetum */
-  {"tg",       HB_TAG('T','A','J',' ')},       /* Tajik */
-  {"th",       HB_TAG('T','H','A',' ')},       /* Thai */
-  {"ti",       HB_TAG('T','G','Y',' ')},       /* Tigrinya */
-  {"tig",      HB_TAG('T','G','R',' ')},       /* Tigre */
-  {"tiv",      HB_TAG('T','I','V',' ')},       /* Tiv */
-  {"tk",       HB_TAG('T','K','M',' ')},       /* Turkmen */
-  {"tl",       HB_TAG('T','G','L',' ')},       /* Tagalog */
-  {"tmh",      HB_TAG('T','M','H',' ')},       /* Tamashek */
-  {"tn",       HB_TAG('T','N','A',' ')},       /* Tswana */
-  {"to",       HB_TAG('T','G','N',' ')},       /* Tonga (Tonga Islands) */
-  {"tod",      HB_TAG('T','O','D','0')},       /* Toma */
-  {"toi",      HB_TAG('T','N','G',' ')},       /* Tonga */
-  {"tpi",      HB_TAG('T','P','I',' ')},       /* Tok Pisin */
-  {"tr",       HB_TAG('T','R','K',' ')},       /* Turkish */
-  {"tru",      HB_TAG('T','U','A',' ')},       /* Turoyo Aramaic */
-  {"ts",       HB_TAG('T','S','G',' ')},       /* Tsonga */
-  {"tt",       HB_TAG('T','A','T',' ')},       /* Tatar */
-  {"tum",      HB_TAG('T','U','M',' ')},       /* Tumbuka */
-  {"tvl",      HB_TAG('T','V','L',' ')},       /* Tuvalu */
-  {"tw",       HB_TAG('T','W','I',' ')},       /* Twi */
-  {"ty",       HB_TAG('T','H','T',' ')},       /* Tahitian */
-  {"tyv",      HB_TAG('T','U','V',' ')},       /* Tuvin */
-  {"tyz",      HB_TAG('T','Y','Z',' ')},       /* Tày */
-  {"tzm",      HB_TAG('T','Z','M',' ')},       /* Central Atlas Tamazight */
-  {"tzo",      HB_TAG('T','Z','O',' ')},       /* Tzotzil */
-  {"udm",      HB_TAG('U','D','M',' ')},       /* Udmurt */
-  {"ug",       HB_TAG('U','Y','G',' ')},       /* Uighur */
-  {"uk",       HB_TAG('U','K','R',' ')},       /* Ukrainian */
-  {"umb",      HB_TAG('U','M','B',' ')},       /* Umbundu */
-  {"unr",      HB_TAG('M','U','N',' ')},       /* Mundari */
-  {"ur",       HB_TAG('U','R','D',' ')},       /* Urdu */
-  {"uz",       HB_TAG('U','Z','B',' ')},       /* Uzbek [macrolanguage] */
-  {"uzn",      HB_TAG('U','Z','B',' ')},       /* Northern Uzbek */
-  {"uzs",      HB_TAG('U','Z','B',' ')},       /* Southern Uzbek */
-  {"ve",       HB_TAG('V','E','N',' ')},       /* Venda */
-  {"vec",      HB_TAG('V','E','C',' ')},       /* Venetian */
-  {"vi",       HB_TAG('V','I','T',' ')},       /* Vietnamese */
-  {"vls",      HB_TAG('F','L','E',' ')},       /* Vlaams */
-  {"vmw",      HB_TAG('M','A','K',' ')},       /* Makhuwa */
-  {"vo",       HB_TAG('V','O','L',' ')},       /* Volapük */
-  {"vro",      HB_TAG('V','R','O',' ')},       /* Võro */
-  {"wa",       HB_TAG('W','L','N',' ')},       /* Walloon */
-  {"war",      HB_TAG('W','A','R',' ')},       /* Waray (Philippines) */
-  {"wbm",      HB_TAG('W','A',' ',' ')},       /* Wa */
-  {"wbr",      HB_TAG('W','A','G',' ')},       /* Wagdi */
-  {"wle",      HB_TAG('S','I','G',' ')},       /* Wolane */
-  {"wo",       HB_TAG('W','L','F',' ')},       /* Wolof */
-  {"wry",      HB_TAG('M','A','W',' ')},       /* Merwari */
-  {"wtm",      HB_TAG('W','T','M',' ')},       /* Mewati */
-  {"xal",      HB_TAG('K','L','M',' ')},       /* Kalmyk */
-  {"xan",      HB_TAG('S','E','K',' ')},       /* Sekota */
-  {"xh",       HB_TAG('X','H','S',' ')},       /* Xhosa */
-  {"xjb",      HB_TAG('X','J','B',' ')},       /* Minjangbal */
-  {"xog",      HB_TAG('X','O','G',' ')},       /* Soga */
-  {"xom",      HB_TAG('K','M','O',' ')},       /* Komo (Sudan) */
-  {"xpe",      HB_TAG('X','P','E',' ')},       /* Kpelle (Liberia) */
-  {"xsl",      HB_TAG('S','S','L',' ')},       /* South Slavey */
-  {"xst",      HB_TAG('S','I','G',' ')},       /* Silt'e (retired code) */
-  {"xwo",      HB_TAG('T','O','D',' ')},       /* Written Oirat (Todo) */
-  {"yao",      HB_TAG('Y','A','O',' ')},       /* Yao */
-  {"yap",      HB_TAG('Y','A','P',' ')},       /* Yapese */
-  {"yi",       HB_TAG('J','I','I',' ')},       /* Yiddish [macrolanguage] */
-  {"yo",       HB_TAG('Y','B','A',' ')},       /* Yoruba */
-  {"yos",      HB_TAG('Q','I','N',' ')},       /* Yos, deprecated by IANA in favor of Zou [zom] */
-  {"yso",      HB_TAG('N','I','S',' ')},       /* Nisi (China) */
-  {"za",       HB_TAG('Z','H','A',' ')},       /* Chuang/Zhuang [macrolanguage] */
-  {"zea",      HB_TAG('Z','E','A',' ')},       /* Zeeuws */
-  {"zgh",      HB_TAG('Z','G','H',' ')},       /* Standard Morrocan Tamazigh */
-  {"zne",      HB_TAG('Z','N','D',' ')},       /* Zande */
-  {"zom",      HB_TAG('Q','I','N',' ')},       /* Zou */
-  {"zu",       HB_TAG('Z','U','L',' ')},       /* Zulu */
-  {"zum",      HB_TAG('L','R','C',' ')},       /* Kumzari */
-  {"zza",      HB_TAG('Z','Z','A',' ')},       /* Zazaki */
-
-  /* The corresponding languages IDs for the following IDs are unclear,
-   * overlap, or are architecturally weird. Needs more research. */
-
-/*{"chp",      HB_TAG('S','A','Y',' ')},*/     /* Sayisi */
-/*{"cwd",      HB_TAG('T','C','R',' ')},*/     /* TH-Cree */
-/*{"emk",      HB_TAG('E','M','K',' ')},*/     /* Eastern Maninkakan */
-/*{"krc",      HB_TAG('B','A','L',' ')},*/     /* Balkar */
-/*{"??",       HB_TAG('B','C','R',' ')},*/     /* Bible Cree */
-/*{"zh?",      HB_TAG('C','H','N',' ')},*/     /* Chinese (seen in Microsoft fonts) */
-/*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/     /* Garshuni */
-/*{"hy?",      HB_TAG('H','Y','E','0')},*/     /* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */
-/*{"ga-Latg?/" HB_TAG('I','R','T',' ')},*/     /* Irish Traditional */
-/*{"krc",      HB_TAG('K','A','R',' ')},*/     /* Karachay */
-/*{"ka-Geok?", HB_TAG('K','G','E',' ')},*/     /* Khutsuri Georgian */
-/*{"kca",      HB_TAG('K','H','K',' ')},*/     /* Khanty-Kazim */
-/*{"kca",      HB_TAG('K','H','S',' ')},*/     /* Khanty-Shurishkar */
-/*{"kca",      HB_TAG('K','H','V',' ')},*/     /* Khanty-Vakhi */
-/*{"kqs, kss", HB_TAG('K','I','S',' ')},*/     /* Kisii */
-/*{"lua",      HB_TAG('L','U','A',' ')},*/     /* Luba-Lulua */
-/*{"mlq",      HB_TAG('M','L','N',' ')},*/     /* Malinke */
-/*{"nso",      HB_TAG('N','S','O',' ')},*/     /* Sotho, Northern */
-/*{"??",       HB_TAG('M','A','L',' ')},*/     /* Malayalam Traditional */
-/*{"csw",      HB_TAG('N','C','R',' ')},*/     /* N-Cree */
-/*{"csw",      HB_TAG('N','H','C',' ')},*/     /* Norway House Cree */
-/*{"el-polyton",       HB_TAG('P','G','R',' ')},*/     /* Polytonic Greek */
-/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh",     HB_TAG('Q','I','N',' ')},*/     /* Chin */
-/*{"??",       HB_TAG('Y','I','C',' ')},*/     /* Yi Classic */
-/*{"zh-Latn-pinyin",   HB_TAG('Z','H','P',' ')},*/     /* Chinese Phonetic */
-};
-
-typedef struct {
-  char language[11];
-  hb_tag_t tag;
-} LangTagLong;
-static const LangTagLong ot_languages_zh[] = {
-  /* Store longest-first, if one is a prefix of another. */
-  {"zh-cn",    HB_TAG('Z','H','S',' ')},       /* Chinese (China) */
-  {"zh-hk",    HB_TAG('Z','H','H',' ')},       /* Chinese (Hong Kong) */
-  {"zh-mo",    HB_TAG('Z','H','H',' ')},       /* Chinese (Macao) */
-  {"zh-sg",    HB_TAG('Z','H','S',' ')},       /* Chinese (Singapore) */
-  {"zh-tw",    HB_TAG('Z','H','T',' ')},       /* Chinese (Taiwan) */
-  {"zh-hans",  HB_TAG('Z','H','S',' ')},       /* Chinese (Simplified) */
-  {"zh-hant-hk",HB_TAG('Z','H','H',' ')},      /* Chinese (Hong Kong) */
-  {"zh-hant-mo",HB_TAG('Z','H','H',' ')},      /* Chinese (Macao) */
-  {"zh-hant",  HB_TAG('Z','H','T',' ')},       /* Chinese (Traditional) */
-};
-
 static int
 lang_compare_first_component (const void *pa,
                              const void *pb)
@@ -895,6 +189,21 @@ lang_compare_first_component (const void *pa,
   return strncmp (a, b, MAX (da, db));
 }
 
+static bool
+subtag_matches (const char *lang_str,
+               const char *limit,
+               const char *subtag)
+{
+  do {
+    const char *s = strstr (lang_str, subtag);
+    if (!s || s >= limit)
+      return false;
+    if (!ISALNUM (s[strlen (subtag)]))
+      return true;
+    lang_str = s + strlen (subtag);
+  } while (true);
+}
+
 static hb_bool_t
 lang_matches (const char *lang_str, const char *spec)
 {
@@ -904,106 +213,186 @@ lang_matches (const char *lang_str, const char *spec)
         (lang_str[len] == '\0' || lang_str[len] == '-');
 }
 
+typedef struct {
+  char language[4];
+  hb_tag_t tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+} LangTag;
+
+#include "hb-ot-tag-table.hh"
+
+/* The corresponding languages IDs for the following IDs are unclear,
+ * overlap, or are architecturally weird. Needs more research. */
+
+/*{"??",       {HB_TAG('B','C','R',' ')}},*/   /* Bible Cree */
+/*{"zh?",      {HB_TAG('C','H','N',' ')}},*/   /* Chinese (seen in Microsoft fonts) */
+/*{"ar-Syrc?", {HB_TAG('G','A','R',' ')}},*/   /* Garshuni */
+/*{"??",       {HB_TAG('N','G','R',' ')}},*/   /* Nagari */
+/*{"??",       {HB_TAG('Y','I','C',' ')}},*/   /* Yi Classic */
+/*{"zh?",      {HB_TAG('Z','H','P',' ')}},*/   /* Chinese Phonetic */
+
 hb_tag_t
 hb_ot_tag_from_language (hb_language_t language)
 {
-  const char *lang_str, *s;
+  unsigned int count = 1;
+  hb_tag_t tags[1];
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
+  return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
+}
 
-  if (language == HB_LANGUAGE_INVALID)
-    return HB_OT_TAG_DEFAULT_LANGUAGE;
+static void
+hb_ot_tags_from_language (const char   *lang_str,
+                         const char   *limit,
+                         unsigned int *count,
+                         hb_tag_t     *tags)
+{
+  const char *s;
 
-  lang_str = hb_language_to_string (language);
+  /* Check for matches of multiple subtags. */
+  if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
+    return;
 
-  s = strstr (lang_str, "x-hbot");
-  if (s) {
-    char tag[4];
-    int i;
-    s += 6;
-    for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-      tag[i] = TOUPPER (s[i]);
-    if (i) {
-      for (; i < 4; i++)
-       tag[i] = ' ';
-      return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+  /* Find a language matching in the first component. */
+  s = strchr (lang_str, '-');
+  {
+    const LangTag *lang_tag;
+    if (s && limit - lang_str >= 6)
+    {
+      const char *extlang_end = strchr (s + 1, '-');
+      /* If there is an extended language tag, use it. */
+      if (3 == (extlang_end ? extlang_end - s - 1 : strlen (s + 1)) &&
+         ISALPHA (s[1]))
+       lang_str = s + 1;
+    }
+    lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
+                                   ARRAY_LENGTH (ot_languages), sizeof (LangTag),
+                                   lang_compare_first_component);
+    if (lang_tag)
+    {
+      unsigned int i;
+      for (i = 0; i < *count && lang_tag->tags[i] != HB_TAG_NONE; i++)
+       tags[i] = lang_tag->tags[i];
+      *count = i;
+      return;
     }
   }
 
-  /*
-   * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonipa")) {
-    return HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
-  }
-
-  /*
-   * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet
-   * also known as Americanist Phonetic Notation.  It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonnapa")) {
-    return HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
+  if (!s)
+    s = lang_str + strlen (lang_str);
+  if (s - lang_str == 3) {
+    /* Assume it's ISO-639-3 and upper-case and use it. */
+    tags[0] = hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    *count = 1;
+    return;
   }
 
-  /*
-   * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syre")) {
-    return HB_TAG('S','Y','R','E');  /* Estrangela Syriac */
-  }
+  *count = 0;
+}
 
-  /*
-   * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrj")) {
-    return HB_TAG('S','Y','R','J');  /* Western Syriac */
+static bool
+parse_private_use_subtag (const char     *private_use_subtag,
+                         unsigned int   *count,
+                         hb_tag_t       *tags,
+                         const char     *prefix,
+                         unsigned char (*normalize) (unsigned char))
+{
+  if (private_use_subtag && count && tags && *count)
+  {
+    const char *s = strstr (private_use_subtag, prefix);
+    if (s)
+    {
+      char tag[4];
+      int i;
+      s += strlen (prefix);
+      for (i = 0; i < 4 && ISALNUM (s[i]); i++)
+       tag[i] = normalize (s[i]);
+      if (i)
+      {
+       for (; i < 4; i++)
+         tag[i] = ' ';
+       tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+       if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
+         tags[0] ^= ~0xDFDFDFDF;
+       *count = 1;
+       return false;
+      }
+    }
   }
+  return true;
+}
 
-  /*
-   * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrn")) {
-    return HB_TAG('S','Y','R','N');  /* Eastern Syriac */
-  }
+/**
+ * hb_ot_tags_from_script_and_language:
+ * @script: an #hb_script_t to convert.
+ * @language: an #hb_language_t to convert.
+ * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
+ * and actual number of script tags retrieved (OUT)
+ * @script_tags: (out) (allow-none): array of size at least @script_count to store the
+ * script tag results
+ * @language_count: (allow-none): maximum number of language tags to retrieve
+ * (IN) and actual number of language tags retrieved (OUT)
+ * @language_tags: (out) (allow-none): array of size at least @language_count to store
+ * the language tag results
+ *
+ * Converts an #hb_script_t and an #hb_language_t to script and language tags.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                    hb_language_t language,
+                                    unsigned int *script_count /* IN/OUT */,
+                                    hb_tag_t     *script_tags /* OUT */,
+                                    unsigned int *language_count /* IN/OUT */,
+                                    hb_tag_t     *language_tags /* OUT */)
+{
+  bool needs_script = true;
 
-  /* Find a language matching in the first component */
+  if (language == HB_LANGUAGE_INVALID)
   {
-    const LangTag *lang_tag;
-    lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
-                                   ARRAY_LENGTH (ot_languages), sizeof (LangTag),
-                                   lang_compare_first_component);
-    if (lang_tag)
-      return lang_tag->tag;
+    if (language_count && language_tags && *language_count)
+      *language_count = 0;
   }
-
-  /* Otherwise, check the Chinese ones */
-  if (0 == lang_compare_first_component (lang_str, "zh"))
+  else
   {
-    unsigned int i;
+    const char *lang_str, *s, *limit, *private_use_subtag;
+    bool needs_language;
 
-    for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
+    lang_str = hb_language_to_string (language);
+    limit = nullptr;
+    private_use_subtag = nullptr;
+    if (lang_str[0] == 'x' && lang_str[1] == '-')
     {
-      const LangTagLong *lang_tag;
-      lang_tag = &ot_languages_zh[i];
-      if (lang_matches (lang_str, lang_tag->language))
-       return lang_tag->tag;
+      private_use_subtag = lang_str;
+    } else {
+      for (s = lang_str + 1; *s; s++)
+      {
+       if (s[-1] == '-' && s[1] == '-')
+       {
+         if (s[0] == 'x')
+         {
+           private_use_subtag = s;
+           if (!limit)
+             limit = s - 1;
+           break;
+         } else if (!limit)
+         {
+           limit = s - 1;
+         }
+       }
+      }
+      if (!limit)
+       limit = s;
     }
 
-    /* Otherwise just return 'ZHS ' */
-    return HB_TAG('Z','H','S',' ');
-  }
+    needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
+    needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
 
-  s = strchr (lang_str, '-');
-  if (!s)
-    s = lang_str + strlen (lang_str);
-  if (s - lang_str == 3) {
-    /* Assume it's ISO-639-3 and upper-case and use it. */
-    return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    if (needs_language && language_count && language_tags && *language_count)
+      hb_ot_tags_from_language (lang_str, limit, language_count, language_tags);
   }
 
-  return HB_OT_TAG_DEFAULT_LANGUAGE;
+  if (needs_script && script_count && script_tags && *script_count)
+    hb_ot_all_tags_from_script (script, script_count, script_tags);
 }
 
 /**
@@ -1023,36 +412,16 @@ hb_ot_tag_to_language (hb_tag_t tag)
   if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
     return nullptr;
 
-  /* struct LangTag has only room for 3-letter language tags. */
-  switch (tag) {
-  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-    return hb_language_from_string ("und-fonnapa", -1);
-  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-    return hb_language_from_string ("und-fonipa", -1);
-  case HB_TAG('S','Y','R',' '):  /* Syriac [macrolanguage] */
-    return hb_language_from_string ("syr", -1);
-  case HB_TAG('S','Y','R','E'):  /* Estrangela Syriac */
-    return hb_language_from_string ("und-Syre", -1);
-  case HB_TAG('S','Y','R','J'):  /* Western Syriac */
-    return hb_language_from_string ("und-Syrj", -1);
-  case HB_TAG('S','Y','R','N'):  /* Eastern Syriac */
-    return hb_language_from_string ("und-Syrn", -1);
+  {
+    hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
+    if (disambiguated_tag != HB_LANGUAGE_INVALID)
+      return disambiguated_tag;
   }
 
   for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
-    if (ot_languages[i].tag == tag)
+    if (ot_languages[i].tags[0] == tag)
       return hb_language_from_string (ot_languages[i].language, -1);
 
-  /* If tag starts with ZH, it's Chinese */
-  if ((tag & 0xFFFF0000u)  == 0x5A480000u) {
-    switch (tag) {
-      case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
-      case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
-      case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
-      default: break; /* Fall through */
-    }
-  }
-
   /* Else return a custom language in the form of "x-hbotABCD" */
   {
     unsigned char buf[11] = "x-hbot";
@@ -1067,9 +436,74 @@ hb_ot_tag_to_language (hb_tag_t tag)
   }
 }
 
+/**
+ * hb_ot_tags_to_script_and_language:
+ * @script_tag: a script tag
+ * @language_tag: a language tag
+ * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
+ * @language: (allow-none): the #hb_language_t corresponding to @script_tag and
+ * @language_tag (OUT).
+ *
+ * Converts a script tag and a language tag to an #hb_script_t and an
+ * #hb_language_t.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                  hb_tag_t       language_tag,
+                                  hb_script_t   *script /* OUT */,
+                                  hb_language_t *language /* OUT */)
+{
+  hb_script_t script_out = hb_ot_tag_to_script (script_tag);
+  if (script)
+    *script = script_out;
+  if (language)
+  {
+    unsigned int script_count = 1;
+    hb_tag_t primary_script_tag[1];
+    hb_ot_tags_from_script_and_language (script_out,
+                                        HB_LANGUAGE_INVALID,
+                                        &script_count,
+                                        primary_script_tag,
+                                        nullptr, nullptr);
+    *language = hb_ot_tag_to_language (language_tag);
+    if (script_count == 0 || primary_script_tag[0] != script_tag)
+    {
+      unsigned char *buf;
+      const char *lang_str = hb_language_to_string (*language);
+      size_t len = strlen (lang_str);
+      buf = (unsigned char *) malloc (len + 11);
+      if (unlikely (!buf))
+      {
+       *language = nullptr;
+      }
+      else
+      {
+       memcpy (buf, lang_str, len);
+       if (lang_str[0] != 'x' || lang_str[1] != '-') {
+         buf[len++] = '-';
+         buf[len++] = 'x';
+       }
+       buf[len++] = '-';
+       buf[len++] = 'h';
+       buf[len++] = 'b';
+       buf[len++] = 's';
+       buf[len++] = 'c';
+       buf[len++] = script_tag >> 24;
+       buf[len++] = (script_tag >> 16) & 0xFF;
+       buf[len++] = (script_tag >> 8) & 0xFF;
+       buf[len++] = script_tag & 0xFF;
+       *language = hb_language_from_string ((char *) buf, len);
+       free (buf);
+      }
+    }
+  }
+}
+
 #ifdef MAIN
 static inline void
-test_langs_sorted (void)
+test_langs_sorted ()
 {
   for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
   {
@@ -1084,7 +518,7 @@ test_langs_sorted (void)
 }
 
 int
-main (void)
+main ()
 {
   test_langs_sorted ();
   return 0;
diff --git a/src/hb-ot-tag.h b/src/hb-ot-tag.h
deleted file mode 100644 (file)
index 54fb747..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, 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
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_TAG_H
-#define HB_OT_TAG_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_DEFAULT_SCRIPT       HB_TAG ('D', 'F', 'L', 'T')
-#define HB_OT_TAG_DEFAULT_LANGUAGE     HB_TAG ('d', 'f', 'l', 't')
-
-HB_EXTERN void
-hb_ot_tags_from_script (hb_script_t  script,
-                       hb_tag_t    *script_tag_1,
-                       hb_tag_t    *script_tag_2);
-
-HB_EXTERN hb_script_t
-hb_ot_tag_to_script (hb_tag_t tag);
-
-HB_EXTERN hb_tag_t
-hb_ot_tag_from_language (hb_language_t language);
-
-HB_EXTERN hb_language_t
-hb_ot_tag_to_language (hb_tag_t tag);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_TAG_H */
index ad063d3..c4a192d 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_AVAR_TABLE_HH
 #define HB_OT_VAR_AVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * avar -- Axis Variations
@@ -42,7 +42,7 @@ namespace OT {
 
 struct AxisValueMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -59,7 +59,7 @@ struct AxisValueMap
 
 struct SegmentMaps : ArrayOf<AxisValueMap>
 {
-  inline int map (int value) const
+  int map (int value) const
   {
     /* The following special-cases are not part of OpenType, which requires
      * that at least -1, 0, and +1 must be mapped. But we include these as
@@ -93,14 +93,15 @@ struct SegmentMaps : ArrayOf<AxisValueMap>
            (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
   }
 
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  public:
+  DEFINE_SIZE_ARRAY (2, *this);
 };
 
 struct avar
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_avar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(version.sanitize (c) &&
@@ -108,7 +109,7 @@ struct avar
                    c->check_struct (this))))
       return_trace (false);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     unsigned int count = axisCount;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -120,11 +121,11 @@ struct avar
     return_trace (true);
   }
 
-  inline void map_coords (int *coords, unsigned int coords_length) const
+  void map_coords (int *coords, unsigned int coords_length) const
   {
     unsigned int count = MIN<unsigned int> (coords_length, axisCount);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     for (unsigned int i = 0; i < count; i++)
     {
       coords[i] = map->map (coords[i]);
@@ -139,7 +140,7 @@ struct avar
   HBUINT16     axisCount;      /* The number of variation axes in the font. This
                                 * must be the same number as axisCount in the
                                 * 'fvar' table. */
-  SegmentMaps  axisSegmentMapsZ[VAR];
+  SegmentMaps   firstAxisSegmentMaps;
 
   public:
   DEFINE_SIZE_MIN (8);
index 82d2996..78cb3c8 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_FVAR_TABLE_HH
 #define HB_OT_VAR_FVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * fvar -- Font Variations
@@ -42,29 +42,40 @@ namespace OT {
 
 struct InstanceRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
+  friend struct fvar;
+
+  hb_array_t<const Fixed> get_coordinates (unsigned int axis_count) const
+  { return coordinatesZ.as_array (axis_count); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 c->check_array (coordinates, coordinates[0].static_size, axis_count));
+                 c->check_array (coordinatesZ.arrayZ, axis_count));
   }
 
   protected:
   NameID       subfamilyNameID;/* The name ID for entries in the 'name' table
                                 * that provide subfamily names for this instance. */
-  HBUINT16     reserved;       /* Reserved for future use — set to 0. */
-  Fixed                coordinates[VAR];/* The coordinates array for this instance. */
+  HBUINT16     flags;          /* Reserved for future use — set to 0. */
+  UnsizedArrayOf<Fixed>
+               coordinatesZ;   /* The coordinates array for this instance. */
   //NameID     postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
   //                             * table that provide PostScript names for this
   //                             * instance. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, coordinates);
+  DEFINE_SIZE_UNBOUNDED (4);
 };
 
 struct AxisRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum
+  {
+    AXIS_FLAG_HIDDEN   = 0x0001,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -75,7 +86,7 @@ struct AxisRecord
   Fixed                minValue;       /* The minimum coordinate value for the axis. */
   Fixed                defaultValue;   /* The default coordinate value for the axis. */
   Fixed                maxValue;       /* The maximum coordinate value for the axis. */
-  HBUINT16     reserved;       /* Reserved for future use — set to 0. */
+  HBUINT16     flags;          /* Axis flags. */
   NameID       axisNameID;     /* The name ID for entries in the 'name' table that
                                 * provide a display name for this axis. */
 
@@ -85,50 +96,80 @@ struct AxisRecord
 
 struct fvar
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_fvar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_fvar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool has_data () const { return version.to_int (); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
                  likely (version.major == 1) &&
                  c->check_struct (this) &&
+                 axisSize == 20 && /* Assumed in our code. */
                  instanceSize >= axisCount * 4 + 4 &&
-                 axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                 instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                 c->check_range (this, things) &&
-                 c->check_range (&StructAtOffset<char> (this, things),
-                                 axisCount * axisSize + instanceCount * instanceSize));
+                 get_axes ().sanitize (c) &&
+                 c->check_range (get_instance (0), instanceCount, instanceSize));
   }
 
-  inline unsigned int get_axis_count (void) const
-  { return axisCount; }
+  unsigned int get_axis_count () const { return axisCount; }
+
+  void get_axis_deprecated (unsigned int axis_index,
+                                  hb_ot_var_axis_t *info) const
+  {
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+  }
 
-  inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
+  void get_axis_info (unsigned int axis_index,
+                     hb_ot_var_axis_info_t *info) const
   {
-    if (unlikely (index >= axisCount))
-      return false;
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->axis_index = axis_index;
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+    info->reserved = 0;
+  }
 
-    if (info)
+  unsigned int get_axes_deprecated (unsigned int      start_offset,
+                                   unsigned int     *axes_count /* IN/OUT */,
+                                   hb_ot_var_axis_t *axes_array /* OUT */) const
+  {
+    if (axes_count)
     {
-      const AxisRecord &axis = get_axes ()[index];
-      info->tag = axis.axisTag;
-      info->name_id =  axis.axisNameID;
-      info->default_value = axis.defaultValue / 65536.;
-      /* Ensure order, to simplify client math. */
-      info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-      info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-    }
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
+      unsigned int count = axisCount;
+      start_offset = MIN (start_offset, count);
 
-    return true;
+      count -= start_offset;
+      axes_array += start_offset;
+
+      count = MIN (count, *axes_count);
+      *axes_count = count;
+
+      for (unsigned int i = 0; i < count; i++)
+       get_axis_deprecated (start_offset + i, axes_array + i);
+    }
+    return axisCount;
   }
 
-  inline unsigned int get_axis_infos (unsigned int      start_offset,
-                                     unsigned int     *axes_count /* IN/OUT */,
-                                     hb_ot_var_axis_t *axes_array /* OUT */) const
+  unsigned int get_axis_infos (unsigned int           start_offset,
+                              unsigned int          *axes_count /* IN/OUT */,
+                              hb_ot_var_axis_info_t *axes_array /* OUT */) const
   {
     if (axes_count)
     {
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
       unsigned int count = axisCount;
       start_offset = MIN (start_offset, count);
 
@@ -139,32 +180,48 @@ struct fvar
       *axes_count = count;
 
       for (unsigned int i = 0; i < count; i++)
-       get_axis (start_offset + i, axes_array + i);
+       get_axis_info (start_offset + i, axes_array + i);
     }
     return axisCount;
   }
 
-  inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
+  bool find_axis_deprecated (hb_tag_t tag,
+                            unsigned int *axis_index,
+                            hb_ot_var_axis_t *info) const
   {
     const AxisRecord *axes = get_axes ();
     unsigned int count = get_axis_count ();
     for (unsigned int i = 0; i < count; i++)
       if (axes[i].axisTag == tag)
       {
-        if (index)
-         *index = i;
-       return get_axis (i, info);
+        if (axis_index)
+         *axis_index = i;
+       get_axis_deprecated (i, info);
+       return true;
       }
-    if (index)
-      *index = HB_OT_VAR_NO_AXIS_INDEX;
+    if (axis_index)
+      *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
     return false;
   }
 
-  inline int normalize_axis_value (unsigned int axis_index, float v) const
+  bool find_axis_info (hb_tag_t tag,
+                      hb_ot_var_axis_info_t *info) const
   {
-    hb_ot_var_axis_t axis;
-    if (!get_axis (axis_index, &axis))
-      return 0;
+    const AxisRecord *axes = get_axes ();
+    unsigned int count = get_axis_count ();
+    for (unsigned int i = 0; i < count; i++)
+      if (axes[i].axisTag == tag)
+      {
+       get_axis_info (i, info);
+       return true;
+      }
+    return false;
+  }
+
+  int normalize_axis_value (unsigned int axis_index, float v) const
+  {
+    hb_ot_var_axis_info_t axis;
+    get_axis_info (axis_index, &axis);
 
     v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
 
@@ -174,20 +231,65 @@ struct fvar
       v = (v - axis.default_value) / (axis.default_value - axis.min_value);
     else
       v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-    return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
+    return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f));
+  }
+
+  unsigned int get_instance_count () const { return instanceCount; }
+
+  hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    return instance->subfamilyNameID;
+  }
+
+  hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    if (instanceSize >= axisCount * 4 + 6)
+      return StructAfter<NameID> (instance->get_coordinates (axisCount));
+    return HB_OT_NAME_ID_INVALID;
+  }
+
+  unsigned int get_instance_coords (unsigned int  instance_index,
+                                          unsigned int *coords_length, /* IN/OUT */
+                                          float        *coords         /* OUT */) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance))
+    {
+      if (coords_length)
+        *coords_length = 0;
+      return 0;
+    }
+
+    if (coords_length && *coords_length)
+    {
+      hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
+                                                        .sub_array (0, *coords_length);
+      for (unsigned int i = 0; i < instanceCoords.length; i++)
+        coords[i] = instanceCoords.arrayZ[i].to_float ();
+    }
+    return axisCount;
   }
 
   protected:
-  inline const AxisRecord * get_axes (void) const
-  { return &StructAtOffset<AxisRecord> (this, things); }
+  hb_array_t<const AxisRecord> get_axes () const
+  { return hb_array (&(this+firstAxis), axisCount); }
 
-  inline const InstanceRecord * get_instances (void) const
-  { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
+  const InstanceRecord *get_instance (unsigned int i) const
+  {
+    if (unlikely (i >= instanceCount)) return nullptr;
+   return &StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
+                                          i * instanceSize);
+  }
 
   protected:
   FixedVersion<>version;       /* Version of the fvar table
                                 * initially set to 0x00010000u */
-  Offset16     things;         /* Offset in bytes from the beginning of the table
+  OffsetTo<AxisRecord>
+               firstAxis;      /* Offset in bytes from the beginning of the table
                                 * to the start of the AxisRecord array. */
   HBUINT16     reserved;       /* This field is permanently reserved. Set to 2. */
   HBUINT16     axisCount;      /* The number of variation axes in the font (the
index 2b384db..a8d9fe3 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_HVAR_TABLE_HH
 #define HB_OT_VAR_HVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,11 +35,13 @@ namespace OT {
 
 struct DeltaSetIndexMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                 c->check_array (mapData, get_width (), mapCount));
+                 c->check_range (mapDataZ.arrayZ,
+                                 mapCount,
+                                 get_width ()));
   }
 
   unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
@@ -55,7 +57,7 @@ struct DeltaSetIndexMap
     unsigned int u = 0;
     { /* Fetch it. */
       unsigned int w = get_width ();
-      const HBUINT8 *p = mapData + w * v;
+      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
       for (; w; w--)
        u = (u << 8) + *p++;
     }
@@ -71,20 +73,19 @@ struct DeltaSetIndexMap
   }
 
   protected:
-  inline unsigned int get_width (void) const
-  { return ((format >> 4) & 3) + 1; }
+  unsigned int get_width () const          { return ((format >> 4) & 3) + 1; }
 
-  inline unsigned int get_inner_bitcount (void) const
-  { return (format & 0xF) + 1; }
+  unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; }
 
   protected:
   HBUINT16     format;         /* A packed field that describes the compressed
                                 * representation of delta-set indices. */
   HBUINT16     mapCount;       /* The number of mapping entries. */
-  HBUINT8              mapData[VAR];   /* The delta-set index mapping data. */
+  UnsizedArrayOf<HBUINT8>
+               mapDataZ;       /* The delta-set index mapping data. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, mapData);
+  DEFINE_SIZE_ARRAY (4, mapDataZ);
 };
 
 
@@ -99,10 +100,10 @@ struct DeltaSetIndexMap
 
 struct HVARVVAR
 {
-  static const hb_tag_t HVARTag        = HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag        = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -113,15 +114,14 @@ struct HVARVVAR
                  rsbMap.sanitize (c, this));
   }
 
-  inline float get_advance_var (hb_codepoint_t glyph,
-                               int *coords, unsigned int coord_count) const
+  float get_advance_var (hb_codepoint_t glyph,
+                        const int *coords, unsigned int coord_count) const
   {
     unsigned int varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx, coords, coord_count);
   }
 
-  inline bool has_sidebearing_deltas (void) const
-  { return lsbMap && rsbMap; }
+  bool has_sidebearing_deltas () const { return lsbMap && rsbMap; }
 
   protected:
   FixedVersion<>version;       /* Version of the metrics variation table
@@ -140,12 +140,12 @@ struct HVARVVAR
 };
 
 struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag       = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR;
 };
 struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag       = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
index dfde782..0dd63e5 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_MVAR_TABLE_HH
 #define HB_OT_VAR_MVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,7 +35,7 @@ namespace OT {
 
 struct VariationValueRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -58,9 +58,9 @@ struct VariationValueRecord
 
 struct MVAR
 {
-  static const hb_tag_t tableTag       = HB_OT_TAG_MVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -68,14 +68,16 @@ struct MVAR
                  c->check_struct (this) &&
                  valueRecordSize >= VariationValueRecord::static_size &&
                  varStore.sanitize (c, this) &&
-                 c->check_array (values, valueRecordSize, valueRecordCount));
+                 c->check_range (valuesZ.arrayZ,
+                                 valueRecordCount,
+                                 valueRecordSize));
   }
 
-  inline float get_var (hb_tag_t tag,
-                       int *coords, unsigned int coord_count) const
+  float get_var (hb_tag_t tag,
+                const int *coords, unsigned int coord_count) const
   {
     const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, values,
+    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
                                               valueRecordCount, valueRecordSize,
                                               tag_compare);
     if (!record)
@@ -85,7 +87,7 @@ struct MVAR
   }
 
 protected:
-  static inline int tag_compare (const void *pa, const void *pb)
+  static int tag_compare (const void *pa, const void *pb)
   {
     const hb_tag_t *a = (const hb_tag_t *) pa;
     const Tag *b = (const Tag *) pb;
@@ -101,11 +103,12 @@ protected:
   HBUINT16     valueRecordCount;/* The number of value records — may be zero. */
   OffsetTo<VariationStore>
                varStore;       /* Offset to item variation store table. */
-  HBUINT8              values[VAR];    /* Array of value records. The records must be
+  UnsizedArrayOf<HBUINT8>
+               valuesZ;        /* Array of value records. The records must be
                                 * in binary order of their valueTag field. */
 
   public:
-  DEFINE_SIZE_ARRAY (12, values);
+  DEFINE_SIZE_ARRAY (12, valuesZ);
 };
 
 } /* namespace OT */
index f0612a6..e327fb7 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-face.hh"
 #include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var-mvar-table.hh"
 #include "hb-ot-var.h"
 
+
+/**
+ * SECTION:hb-ot-var
+ * @title: hb-ot-var
+ * @short_description: OpenType Font Variations
+ * @include: hb-ot.h
+ *
+ * Functions for fetching information about OpenType Variable Fonts.
+ **/
+
+
 /*
  * fvar/avar
  */
 
-static inline const OT::fvar&
-_get_fvar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->fvar.get ());
-}
-static inline const OT::avar&
-_get_avar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->avar.get ());
-}
 
 /**
  * hb_ot_var_has_data:
  * @face: #hb_face_t to test
  *
  * This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
  *
  * Return value: true if face has a `fvar' table and false otherwise
  *
@@ -65,7 +61,7 @@ _get_avar (hb_face_t *face)
 hb_bool_t
 hb_ot_var_has_data (hb_face_t *face)
 {
-  return &_get_fvar (face) != &Null(OT::fvar);
+  return face->table.fvar->has_data ();
 }
 
 /**
@@ -76,14 +72,14 @@ hb_ot_var_has_data (hb_face_t *face)
 unsigned int
 hb_ot_var_get_axis_count (hb_face_t *face)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_count ();
+  return face->table.fvar->get_axis_count ();
 }
 
 /**
  * hb_ot_var_get_axes:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 unsigned int
 hb_ot_var_get_axes (hb_face_t        *face,
@@ -91,14 +87,14 @@ hb_ot_var_get_axes (hb_face_t        *face,
                    unsigned int     *axes_count /* IN/OUT */,
                    hb_ot_var_axis_t *axes_array /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_infos (start_offset, axes_count, axes_array);
+  return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array);
 }
 
 /**
  * hb_ot_var_find_axis:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 hb_bool_t
 hb_ot_var_find_axis (hb_face_t        *face,
@@ -106,8 +102,68 @@ hb_ot_var_find_axis (hb_face_t        *face,
                     unsigned int     *axis_index,
                     hb_ot_var_axis_t *axis_info)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.find_axis (axis_tag, axis_index, axis_info);
+  return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
+}
+
+/**
+ * hb_ot_var_get_axis_infos:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                         unsigned int           start_offset,
+                         unsigned int          *axes_count /* IN/OUT */,
+                         hb_ot_var_axis_info_t *axes_array /* OUT */)
+{
+  return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
+}
+
+/**
+ * hb_ot_var_find_axis_info:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                         hb_tag_t               axis_tag,
+                         hb_ot_var_axis_info_t *axis_info)
+{
+  return face->table.fvar->find_axis_info (axis_tag, axis_info);
+}
+
+
+/*
+ * Named instances.
+ */
+
+unsigned int
+hb_ot_var_get_named_instance_count (hb_face_t *face)
+{
+  return face->table.fvar->get_instance_count ();
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                               unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_subfamily_name_id (instance_index);
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                               unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_postscript_name_id (instance_index);
+}
+
+unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                           unsigned int  instance_index,
+                                           unsigned int *coords_length, /* IN/OUT */
+                                           float        *coords         /* OUT */)
+{
+  return face->table.fvar->get_instance_coords (instance_index, coords_length, coords);
 }
 
 
@@ -126,17 +182,16 @@ hb_ot_var_normalize_variations (hb_face_t            *face,
   for (unsigned int i = 0; i < coords_length; i++)
     coords[i] = 0;
 
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < variations_length; i++)
   {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
-       axis_index < coords_length)
-      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
+    hb_ot_var_axis_info_t info;
+    if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
+       info.axis_index < coords_length)
+      coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
   }
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (coords, coords_length);
+  face->table.avar->map_coords (coords, coords_length);
 }
 
 /**
@@ -150,10 +205,9 @@ hb_ot_var_normalize_coords (hb_face_t    *face,
                            const float *design_coords, /* IN */
                            int *normalized_coords /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < coords_length; i++)
     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (normalized_coords, coords_length);
+  face->table.avar->map_coords (normalized_coords, coords_length);
 }
index a2c0c5f..cf6f0c9 100644 (file)
@@ -47,44 +47,85 @@ HB_BEGIN_DECLS
  * fvar / avar
  */
 
+HB_EXTERN hb_bool_t
+hb_ot_var_has_data (hb_face_t *face);
+
+
+/*
+ * Variation axes.
+ */
+
+
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_count (hb_face_t *face);
+
 /**
- * hb_ot_var_axis_t:
+ * hb_ot_var_axis_flags_t:
+ * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
  *
- * Since: 1.4.2
+ * Since: 2.2.0
  */
-typedef struct hb_ot_var_axis_t {
-  hb_tag_t tag;
-  unsigned int name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
+typedef enum { /*< flags >*/
+  HB_OT_VAR_AXIS_FLAG_HIDDEN   = 0x00000001u,
 
-HB_EXTERN hb_bool_t
-hb_ot_var_has_data (hb_face_t *face);
+  _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
+} hb_ot_var_axis_flags_t;
 
 /**
- * HB_OT_VAR_NO_AXIS_INDEX:
+ * hb_ot_var_axis_info_t:
  *
- * Since: 1.4.2
+ * Since: 2.2.0
  */
-#define HB_OT_VAR_NO_AXIS_INDEX                0xFFFFFFFFu
+typedef struct hb_ot_var_axis_info_t
+{
+  unsigned int                 axis_index;
+  hb_tag_t                     tag;
+  hb_ot_name_id_t              name_id;
+  hb_ot_var_axis_flags_t       flags;
+  float                                min_value;
+  float                                default_value;
+  float                                max_value;
+  /*< private >*/
+  unsigned int                 reserved;
+} hb_ot_var_axis_info_t;
 
 HB_EXTERN unsigned int
-hb_ot_var_get_axis_count (hb_face_t *face);
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                         unsigned int           start_offset,
+                         unsigned int          *axes_count /* IN/OUT */,
+                         hb_ot_var_axis_info_t *axes_array /* OUT */);
+
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                         hb_tag_t               axis_tag,
+                         hb_ot_var_axis_info_t *axis_info);
+
+
+/*
+ * Named instances.
+ */
 
 HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-                   unsigned int      start_offset,
-                   unsigned int     *axes_count /* IN/OUT */,
-                   hb_ot_var_axis_t *axes_array /* OUT */);
+hb_ot_var_get_named_instance_count (hb_face_t *face);
 
-HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-                    hb_tag_t          axis_tag,
-                    unsigned int     *axis_index,
-                    hb_ot_var_axis_t *axis_info);
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                               unsigned int instance_index);
 
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                               unsigned int instance_index);
+
+HB_EXTERN unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                           unsigned int  instance_index,
+                                           unsigned int *coords_length, /* IN/OUT */
+                                           float        *coords         /* OUT */);
+
+
+/*
+ * Conversions.
+ */
 
 HB_EXTERN void
 hb_ot_var_normalize_variations (hb_face_t            *face,
diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh
new file mode 100644 (file)
index 0000000..0202fcc
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_VORG_TABLE_HH
+#define HB_OT_VORG_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * VORG -- Vertical Origin Table
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg
+ */
+#define HB_OT_TAG_VORG HB_TAG('V','O','R','G')
+
+namespace OT {
+
+struct VertOriginMetric
+{
+  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  GlyphID      glyph;
+  FWORD                vertOriginY;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct VORG
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VORG;
+
+  bool has_data () const { return version.to_int (); }
+
+  int get_y_origin (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    if (!vertYOrigins.bfind (glyph, &i))
+      return defaultVertOriginY;
+    return vertYOrigins[i].vertOriginY;
+  }
+
+  bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
+               const VORG *vorg_table,
+               const hb_vector_t<VertOriginMetric> &subset_metrics,
+               unsigned int dest_sz,
+               void *dest) const
+  {
+    hb_serialize_context_t c (dest, dest_sz);
+
+    VORG *subset_table = c.start_serialize<VORG> ();
+    if (unlikely (!c.extend_min (*subset_table)))
+      return false;
+
+    subset_table->version.major.set (1);
+    subset_table->version.minor.set (0);
+
+    subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY);
+    subset_table->vertYOrigins.len.set (subset_metrics.length);
+
+    bool success = true;
+    if (subset_metrics.length > 0)
+    {
+      unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
+      VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
+      if (likely (metrics != nullptr))
+        memcpy (metrics, &subset_metrics[0], size);
+      else
+        success = false;
+    }
+    c.end_serialize ();
+
+    return success;
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source);
+    const VORG *vorg_table = vorg_blob->as<VORG> ();
+
+    /* count the number of glyphs to be included in the subset table */
+    hb_vector_t<VertOriginMetric> subset_metrics;
+    subset_metrics.init ();
+    unsigned int glyph = 0;
+    unsigned int i = 0;
+    while ((glyph < plan->glyphs.length) && (i < vertYOrigins.len))
+    {
+      if (plan->glyphs[glyph] > vertYOrigins[i].glyph)
+        i++;
+      else if (plan->glyphs[glyph] < vertYOrigins[i].glyph)
+        glyph++;
+      else
+      {
+        VertOriginMetric *metrics = subset_metrics.push ();
+        metrics->glyph.set (glyph);
+        metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
+        glyph++;
+        i++;
+      }
+    }
+
+    /* alloc the new table */
+    unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
+    void *dest = (void *) malloc (dest_sz);
+    if (unlikely (!dest))
+    {
+      subset_metrics.fini ();
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    /* serialize the new table */
+    if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest))
+    {
+      subset_metrics.fini ();
+      free (dest);
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    hb_blob_t *result = hb_blob_create ((const char *)dest,
+                                        dest_sz,
+                                        HB_MEMORY_MODE_READONLY,
+                                        dest,
+                                        free);
+    bool success = plan->add_table (HB_OT_TAG_VORG, result);
+    hb_blob_destroy (result);
+    subset_metrics.fini ();
+    hb_blob_destroy (vorg_blob);
+    return success;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  version.major == 1 &&
+                  vertYOrigins.sanitize (c));
+  }
+
+  protected:
+  FixedVersion<>       version;                /* Version of VORG table. Set to 0x00010000u. */
+  FWORD                        defaultVertOriginY;     /* The default vertical origin. */
+  SortedArrayOf<VertOriginMetric>
+                       vertYOrigins;           /* The array of vertical origins. */
+
+  public:
+  DEFINE_SIZE_ARRAY(8, vertYOrigins);
+};
+} /* namespace OT */
+
+#endif /* HB_OT_VORG_TABLE_HH */
index 2120a3e..db78469 100644 (file)
 
 #include "hb.h"
 
+#include "hb-ot-color.h"
+#include "hb-ot-deprecated.h"
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 #include "hb-ot-shape.h"
 #include "hb-ot-var.h"
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
deleted file mode 100644 (file)
index 32e3354..0000000
+++ /dev/null
@@ -1,1241 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2011,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
- */
-
-#ifndef HB_PRIVATE_HH
-#define HB_PRIVATE_HH
-
-#define _GNU_SOURCE 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb.h"
-#define HB_H_IN
-#ifdef HAVE_OT
-#include "hb-ot.h"
-#define HB_OT_H_IN
-#endif
-
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-#include <intrin.h>
-#endif
-
-#define HB_PASTE1(a,b) a##b
-#define HB_PASTE(a,b) HB_PASTE1(a,b)
-
-/* Compile-time custom allocator support. */
-
-#if defined(hb_malloc_impl) \
- && defined(hb_calloc_impl) \
- && defined(hb_realloc_impl) \
- && defined(hb_free_impl)
-extern "C" void* hb_malloc_impl(size_t size);
-extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
-extern "C" void* hb_realloc_impl(void *ptr, size_t size);
-extern "C" void  hb_free_impl(void *ptr);
-#define malloc hb_malloc_impl
-#define calloc hb_calloc_impl
-#define realloc hb_realloc_impl
-#define free hb_free_impl
-#endif
-
-
-/* Compiler attributes */
-
-
-#if __cplusplus < 201103L
-
-#ifndef nullptr
-#define nullptr NULL
-#endif
-
-// Static assertions
-#ifndef static_assert
-#define static_assert(e, msg) \
-       HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
-#endif // static_assert
-
-#ifdef __GNUC__
-#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
-#define thread_local __thread
-#endif
-#else
-#define thread_local
-#endif
-
-#endif // __cplusplus < 201103L
-
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
-#define likely(expr) (__builtin_expect (!!(expr), 1))
-#define unlikely(expr) (__builtin_expect (!!(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#if !defined(__GNUC__) && !defined(__clang__)
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC   __attribute__((pure))
-#define HB_CONST_FUNC  __attribute__((const))
-#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#define HB_PRINTF_FUNC(format_idx, arg_idx)
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED      __attribute__((unused))
-#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
-#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
-#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
-#  define HB_INTERNAL
-#  define HB_NO_VISIBILITY 1
-# endif
-#endif
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
-/* https://github.com/harfbuzz/harfbuzz/issues/630 */
-#define __restrict
-#endif
-
-/*
- * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
- * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
- * cases that fall through without a break or return statement. HB_FALLTHROUGH
- * is only needed on cases that have code:
- *
- * switch (foo) {
- *   case 1: // These cases have no code. No fallthrough annotations are needed.
- *   case 2:
- *   case 3:
- *     foo = 4; // This case has code, so a fallthrough annotation is needed:
- *     HB_FALLTHROUGH;
- *   default:
- *     return foo;
- * }
- */
-#if defined(__clang__) && __cplusplus >= 201103L
-   /* clang's fallthrough annotations are only available starting in C++11. */
-#  define HB_FALLTHROUGH [[clang::fallthrough]]
-#elif __GNUC__ >= 7
-   /* GNU fallthrough attribute is available from GCC7 */
-#  define HB_FALLTHROUGH __attribute__((fallthrough))
-#elif defined(_MSC_VER)
-   /*
-    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
-    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-    */
-#  include <sal.h>
-#  define HB_FALLTHROUGH __fallthrough
-#else
-#  define HB_FALLTHROUGH /* FALLTHROUGH */
-#endif
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-   /* We need Windows Vista for both Uniscribe backend and for
-    * MemoryBarrier.  We don't support compiling on Windows XP,
-    * though we run on it fine. */
-#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
-#    undef _WIN32_WINNT
-#  endif
-#  ifndef _WIN32_WINNT
-#    define _WIN32_WINNT 0x0600
-#  endif
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN 1
-#  endif
-#  ifndef STRICT
-#    define STRICT 1
-#  endif
-
-#  if defined(_WIN32_WCE)
-     /* Some things not defined on Windows CE. */
-#    define vsnprintf _vsnprintf
-#    define getenv(Name) nullptr
-#    if _WIN32_WCE < 0x800
-#      define setlocale(Category, Locale) "C"
-static int errno = 0; /* Use something better? */
-#    endif
-#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#    define getenv(Name) nullptr
-#  endif
-#  if defined(_MSC_VER) && _MSC_VER < 1900
-#    define snprintf _snprintf
-#  endif
-#endif
-
-#if HAVE_ATEXIT
-/* atexit() is only safe to be called from shared libraries on certain
- * platforms.  Whitelist.
- * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
-#  if defined(__linux) && defined(__GLIBC_PREREQ)
-#    if __GLIBC_PREREQ(2,3)
-/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
-#      define HB_USE_ATEXIT 1
-#    endif
-#  elif defined(_MSC_VER) || defined(__MINGW32__)
-/* For MSVC:
- * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
- * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
- * mingw32 headers say atexit is safe to use in shared libraries.
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__ANDROID__)
-/* This is available since Android NKD r8 or r8b:
- * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__APPLE__)
-/* For macOS and related platforms, the atexit man page indicates
- * that it will be invoked when the library is unloaded, not only
- * at application exit.
- */
-#    define HB_USE_ATEXIT 1
-#  endif
-#endif
-#ifdef HB_NO_ATEXIT
-#  undef HB_USE_ATEXIT
-#endif
-
-/* Basics */
-
-#undef MIN
-template <typename Type>
-static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type>
-static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
-static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
-{ return (a + (b - 1)) / b; }
-
-
-#undef  ARRAY_LENGTH
-template <typename Type, unsigned int n>
-static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-/* A const version, but does not detect erratically being called on pointers. */
-#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define HB_STMT_START do
-#define HB_STMT_END   while (0)
-
-template <unsigned int cond> class hb_assert_constant_t;
-template <> class hb_assert_constant_t<1> {};
-
-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
-
-/* Lets assert int types.  Saves trouble down the road. */
-
-static_assert ((sizeof (int8_t) == 1), "");
-static_assert ((sizeof (uint8_t) == 1), "");
-static_assert ((sizeof (int16_t) == 2), "");
-static_assert ((sizeof (uint16_t) == 2), "");
-static_assert ((sizeof (int32_t) == 4), "");
-static_assert ((sizeof (uint32_t) == 4), "");
-static_assert ((sizeof (int64_t) == 8), "");
-static_assert ((sizeof (uint64_t) == 8), "");
-
-static_assert ((sizeof (hb_codepoint_t) == 4), "");
-static_assert ((sizeof (hb_position_t) == 4), "");
-static_assert ((sizeof (hb_mask_t) == 4), "");
-static_assert ((sizeof (hb_var_int_t) == 4), "");
-
-
-/* We like our types POD */
-
-#define _ASSERT_TYPE_POD1(_line, _type)        union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
-#define _ASSERT_TYPE_POD0(_line, _type)        _ASSERT_TYPE_POD1 (_line, _type)
-#define ASSERT_TYPE_POD(_type)         _ASSERT_TYPE_POD0 (__LINE__, _type)
-
-#ifdef __GNUC__
-# define _ASSERT_INSTANCE_POD1(_line, _instance) \
-       HB_STMT_START { \
-               typedef __typeof__(_instance) _type_##_line; \
-               _ASSERT_TYPE_POD1 (_line, _type_##_line); \
-       } HB_STMT_END
-#else
-# define _ASSERT_INSTANCE_POD1(_line, _instance)       typedef int _assertion_on_line_##_line##_not_tested
-#endif
-# define _ASSERT_INSTANCE_POD0(_line, _instance)       _ASSERT_INSTANCE_POD1 (_line, _instance)
-# define ASSERT_INSTANCE_POD(_instance)                        _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
-
-/* Check _assertion in a method environment */
-#define _ASSERT_POD1(_line) \
-       HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
-       { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
-# define _ASSERT_POD0(_line)   _ASSERT_POD1 (_line)
-# define ASSERT_POD()          _ASSERT_POD0 (__LINE__)
-
-
-
-/* Tiny functions */
-
-/*
- * Void!
- */
-typedef const struct _hb_void_t *hb_void_t;
-#define HB_VOID ((const _hb_void_t *) nullptr)
-
-/* Return the number of 1 bits in v. */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount (T v)
-{
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_popcount (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_popcountl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_popcountll (v);
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "HACKMEM 169" */
-    uint32_t y;
-    y = (v >> 1) &033333333333;
-    y = v - y - ((y >>1) & 033333333333);
-    return (((y + (y >> 3)) & 030707070707) % 077);
-  }
-
-  if (sizeof (T) == 8)
-  {
-    unsigned int shift = 32;
-    return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift));
-  }
-
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift));
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of bits needed to store number */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return sizeof (unsigned int) * 8 - __builtin_clz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanReverse (&where, v);
-    return 1 + where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanReverse64 (&where, v);
-    return 1 + where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-    const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 0;
-    for (int i = 4; i >= 0; i--)
-      if (v & b[i])
-      {
-       v >>= S[i];
-       r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
-    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 0;
-    for (int i = 5; i >= 0; i--)
-      if (v & b[i])
-      {
-       v >>= S[i];
-       r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
-                         _hb_bit_storage<uint64_t> ((uint64_t) v);
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of zero bits in the least significant side of v */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_ctz (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_ctz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_ctzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_ctzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanForward (&where, v);
-    return where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanForward64 (&where, v);
-    return where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    unsigned int c = 32;
-    v &= - (int32_t) v;
-    if (v) c--;
-    if (v & 0x0000FFFF) c -= 16;
-    if (v & 0x00FF00FF) c -= 8;
-    if (v & 0x0F0F0F0F) c -= 4;
-    if (v & 0x33333333) c -= 2;
-    if (v & 0x55555555) c -= 1;
-    return c;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    unsigned int c = 64;
-    v &= - (int64_t) (v);
-    if (v) c--;
-    if (v & 0x00000000FFFFFFFFULL) c -= 32;
-    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
-    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
-    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
-    if (v & 0x3333333333333333ULL) c -= 2;
-    if (v & 0x5555555555555555ULL) c -= 1;
-    return c;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) :
-                         _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift;
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-static inline bool
-_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
-{
-  return (size > 0) && (count >= ((unsigned int) -1) / size);
-}
-
-static inline unsigned int
-_hb_ceil_to_4 (unsigned int v)
-{
-  return ((v - 1) | 3) + 1;
-}
-
-
-
-/*
- *
- * Utility types
- *
- */
-
-#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&); \
-  void operator=(const TypeName&)
-
-/*
- * Static pools
- */
-
-/* Global nul-content Null pool.  Enlarge as necessary. */
-
-#define HB_NULL_POOL_SIZE 264
-static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline Type const & Null (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
-#define Null(Type) Null<Type>()
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Namespace, Type, data) \
-} /* Close namespace. */ \
-static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
-} \
-namespace Namespace { \
-/* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.  Enlarge.")
-
-
-/* Global writable pool.  Enlarge as necessary. */
-
-/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
- * for correct operation. It only exist to catch and divert program logic bugs instead of
- * causing bad memory access. So, races there are not actually introducing incorrectness
- * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* CRAP pool: Common Region for Access Protection. */
-template <typename Type>
-static inline Type& Crap (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  *obj = Null(Type);
-  return *obj;
-}
-#define Crap(Type) Crap<Type>()
-
-template <typename Type>
-struct CrapOrNull {
-  static inline Type & get (void) { return Crap(Type); }
-};
-template <typename Type>
-struct CrapOrNull<const Type> {
-  static inline Type const & get (void) { return Null(Type); }
-};
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
-
-
-
-/* arrays and maps */
-
-
-#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
-template <typename Type, unsigned int StaticSize=8>
-struct hb_vector_t
-{
-  unsigned int len;
-  unsigned int allocated;
-  bool successful;
-  Type *arrayZ;
-  Type static_array[StaticSize];
-
-  void init (void)
-  {
-    len = 0;
-    allocated = ARRAY_LENGTH (static_array);
-    successful = true;
-    arrayZ = static_array;
-  }
-
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len))
-      return Crap (Type);
-    return arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len))
-      return Null(Type);
-    return arrayZ[i];
-  }
-
-  inline Type *push (void)
-  {
-    if (unlikely (!resize (len + 1)))
-      return &Crap(Type);
-    return &arrayZ[len - 1];
-  }
-  inline Type *push (const Type& v)
-  {
-    Type *p = push ();
-    *p = v;
-    return p;
-  }
-
-  /* Allocate for size but don't adjust len. */
-  inline bool alloc (unsigned int size)
-  {
-    if (unlikely (!successful))
-      return false;
-
-    if (likely (size <= allocated))
-      return true;
-
-    /* Reallocate */
-
-    unsigned int new_allocated = allocated;
-    while (size >= new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    Type *new_array = nullptr;
-
-    if (arrayZ == static_array)
-    {
-      new_array = (Type *) calloc (new_allocated, sizeof (Type));
-      if (new_array)
-        memcpy (new_array, arrayZ, len * sizeof (Type));
-    }
-    else
-    {
-      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
-      if (likely (!overflows))
-        new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
-    }
-
-    if (unlikely (!new_array))
-    {
-      successful = false;
-      return false;
-    }
-
-    arrayZ = new_array;
-    allocated = new_allocated;
-
-    return true;
-  }
-
-  inline bool resize (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-    if (!alloc (size))
-      return false;
-
-    if (size > len)
-      memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
-
-    len = size;
-    return true;
-  }
-
-  inline void pop (void)
-  {
-    if (!len) return;
-    len--;
-  }
-
-  inline void remove (unsigned int i)
-  {
-     if (unlikely (i >= len))
-       return;
-     memmove (static_cast<void *> (&arrayZ[i]),
-             static_cast<void *> (&arrayZ[i + 1]),
-             (len - i - 1) * sizeof (Type));
-     len--;
-  }
-
-  inline void shrink (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-     if (size < len)
-       len = size;
-  }
-
-  template <typename T>
-  inline Type *find (T v) {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-       return &arrayZ[i];
-    return nullptr;
-  }
-  template <typename T>
-  inline const Type *find (T v) const {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-       return &arrayZ[i];
-    return nullptr;
-  }
-
-  inline void qsort (int (*cmp)(const void*, const void*))
-  {
-    ::qsort (arrayZ, len, sizeof (Type), cmp);
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  inline void qsort (unsigned int start, unsigned int end)
-  {
-    ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
-  }
-
-  template <typename T>
-  inline Type *lsearch (const T &x)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      if (0 == this->arrayZ[i].cmp (&x))
-       return &arrayZ[i];
-    return nullptr;
-  }
-
-  template <typename T>
-  inline Type *bsearch (const T &x)
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline const Type *bsearch (const T &x) const
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline bool bfind (const T &x, unsigned int *i) const
-  {
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = this->arrayZ[mid].cmp (&x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-      {
-        *i = mid;
-       return true;
-      }
-    }
-    if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
-      max++;
-    *i = max;
-    return false;
-  }
-
-  inline void fini (void)
-  {
-    if (arrayZ != static_array)
-      free (arrayZ);
-    arrayZ = nullptr;
-    allocated = len = 0;
-  }
-};
-
-template <typename Type>
-struct hb_auto_t : Type
-{
-  hb_auto_t (void) { Type::init (); }
-  ~hb_auto_t (void) { Type::fini (); }
-  private: /* Hide */
-  void init (void) {}
-  void fini (void) {}
-};
-template <typename Type>
-struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
-  hb_vector_t <item_t, 1> items;
-
-  inline void init (void) { items.init (); }
-
-  template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      if (replace) {
-       item_t old = *item;
-       *item = v;
-       l.unlock ();
-       old.fini ();
-      }
-      else {
-        item = nullptr;
-       l.unlock ();
-      }
-    } else {
-      item = items.push (v);
-      l.unlock ();
-    }
-    return item;
-  }
-
-  template <typename T>
-  inline void remove (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      item_t old = *item;
-      *item = items[items.len - 1];
-      items.pop ();
-      l.unlock ();
-      old.fini ();
-    } else {
-      l.unlock ();
-    }
-  }
-
-  template <typename T>
-  inline bool find (T v, item_t *i, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item)
-      *i = *item;
-    l.unlock ();
-    return !!item;
-  }
-
-  template <typename T>
-  inline item_t *find_or_insert (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (!item) {
-      item = items.push (v);
-    }
-    l.unlock ();
-    return item;
-  }
-
-  inline void fini (lock_t &l)
-  {
-    if (!items.len) {
-      /* No need for locking. */
-      items.fini ();
-      return;
-    }
-    l.lock ();
-    while (items.len) {
-      item_t old = items[items.len - 1];
-       items.pop ();
-       l.unlock ();
-       old.fini ();
-       l.lock ();
-    }
-    items.fini ();
-    l.unlock ();
-  }
-
-};
-
-
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-
-
-/* HB_NDEBUG disables some sanity checks that are very safe to disable and
- * should be disabled in production systems.  If NDEBUG is defined, enable
- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
- * the costlier checks. */
-#ifdef NDEBUG
-#define HB_NDEBUG 1
-#endif
-
-
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
-  /* The sizeof() is here to force template instantiation.
-   * I'm sure there are better ways to do this but can't think of
-   * one right now.  Declaring a variable won't work as HB_UNUSED
-   * is unusable on some platforms and unused types are less likely
-   * to generate a warning than unused variables. */
-  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
-  /* The casts below are important as if T is smaller than int,
-   * the subtract results will become a signed int! */
-  return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
-
-/* Enable bitwise ops on enums marked as flags_t */
-/* To my surprise, looks like the function resolver is happy to silently cast
- * one enum to another...  So this doesn't provide the type-checking that I
- * originally had in mind... :(.
- *
- * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
- */
-#ifdef _MSC_VER
-# pragma warning(disable:4200)
-# pragma warning(disable:4800)
-#endif
-#define HB_MARK_AS_FLAG_T(T) \
-       extern "C++" { \
-         static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
-         static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
-         static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
-         static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
-         static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
-         static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
-         static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
-       }
-
-
-/* Useful for set-operations on small enums.
- * For example, for testing "x ∈ {x1, x2, x3}" use:
- * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
- */
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
-#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
-#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-
-
-template <typename T, typename T2> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
-{
-  for (unsigned int i = 1; i < len; i++)
-  {
-    unsigned int j = i;
-    while (j && compar (&array[j - 1], &array[i]) > 0)
-      j--;
-    if (i == j)
-      continue;
-    /* Move item i to occupy place for item j, shift what's in between. */
-    {
-      T t = array[i];
-      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
-      array[j] = t;
-    }
-    if (array2)
-    {
-      T2 t = array2[i];
-      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
-      array2[j] = t;
-    }
-  }
-}
-
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
-  hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
-static inline hb_bool_t
-hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
-{
-  /* Pain because we don't know whether s is nul-terminated. */
-  char buf[64];
-  len = MIN (ARRAY_LENGTH (buf) - 1, len);
-  strncpy (buf, s, len);
-  buf[len] = '\0';
-
-  char *end;
-  errno = 0;
-  unsigned long v = strtoul (buf, &end, base);
-  if (errno) return false;
-  if (*end) return false;
-  *out = v;
-  return true;
-}
-
-
-/* Vectorization */
-
-struct HbOpOr
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
-};
-struct HbOpAnd
-{
-  static const bool passthru_left = false;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
-};
-struct HbOpMinus
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
-};
-struct HbOpXor
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
-};
-
-
-/* Compiler-assisted vectorization. */
-
-/* The `vector_size' attribute was introduced in gcc 3.1. */
-#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
-#define HB_VECTOR_SIZE 128
-#elif !defined(HB_VECTOR_SIZE)
-#define HB_VECTOR_SIZE 0
-#endif
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
-  elt_t& operator [] (unsigned int i) { return u.v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
-
-  template <class Op>
-  inline hb_vector_size_t process (const hb_vector_size_t &o) const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-       Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
-    else
-#endif
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-       Op::process (r.u.v[i], u.v[i], o.u.v[i]);
-    return r;
-  }
-  inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process<HbOpOr> (o); }
-  inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process<HbOpAnd> (o); }
-  inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process<HbOpXor> (o); }
-  inline hb_vector_size_t operator ~ () const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE && 0
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-       r.u.vec[i] = ~u.vec[i];
-    else
-#endif
-    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-      r.u.v[i] = ~u.v[i];
-    return r;
-  }
-
-  private:
-  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-  union {
-    elt_t v[byte_size / sizeof (elt_t)];
-#if HB_VECTOR_SIZE
-    typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
-    vec_t vec[byte_size / sizeof (vec_t)];
-#endif
-  } u;
-};
-
-
-/* Global runtime options. */
-
-struct hb_options_t
-{
-  unsigned int initialized : 1;
-  unsigned int uniscribe_bug_compatible : 1;
-};
-
-union hb_options_union_t {
-  unsigned int i;
-  hb_options_t opts;
-};
-static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
-
-HB_INTERNAL void
-_hb_options_init (void);
-
-extern HB_INTERNAL hb_options_union_t _hb_options;
-
-static inline hb_options_t
-hb_options (void)
-{
-  if (unlikely (!_hb_options.i))
-    _hb_options_init ();
-
-  return _hb_options.opts;
-}
-
-/* Size signifying variable-sized array */
-#define VAR 1
-
-
-/* String type. */
-
-struct hb_bytes_t
-{
-  inline hb_bytes_t (void) : bytes (nullptr), len (0) {}
-  inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
-
-  inline int cmp (const hb_bytes_t &a) const
-  {
-    if (len != a.len)
-      return (int) a.len - (int) len;
-
-    return memcmp (a.bytes, bytes, len);
-  }
-  static inline int cmp (const void *pa, const void *pb)
-  {
-    hb_bytes_t *a = (hb_bytes_t *) pa;
-    hb_bytes_t *b = (hb_bytes_t *) pb;
-    return b->cmp (*a);
-  }
-
-  const char *bytes;
-  unsigned int len;
-};
-
-
-/* fallback for round() */
-#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
-static inline double
-round (double x)
-{
-  if (x >= 0)
-    return floor (x + 0.5);
-  else
-    return ceil (x - 0.5);
-}
-#endif
-
-
-#endif /* HB_PRIVATE_HH */
diff --git a/src/hb-set-digest-private.hh b/src/hb-set-digest-private.hh
deleted file mode 100644 (file)
index e099a82..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_DIGEST_PRIVATE_HH
-#define HB_SET_DIGEST_PRIVATE_HH
-
-#include "hb-private.hh"
-
-/*
- * The set digests here implement various "filters" that support
- * "approximate member query".  Conceptually these are like Bloom
- * Filter and Quotient Filter, however, much smaller, faster, and
- * designed to fit the requirements of our uses for glyph coverage
- * queries.
- *
- * Our filters are highly accurate if the lookup covers fairly local
- * set of glyphs, but fully flooded and ineffective if coverage is
- * all over the place.
- *
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
- */
-
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
-{
-  ASSERT_POD ();
-
-  static const unsigned int mask_bytes = sizeof (mask_t);
-  static const unsigned int mask_bits = sizeof (mask_t) * 8;
-  static const unsigned int num_bits = 0
-                                    + (mask_bytes >= 1 ? 3 : 0)
-                                    + (mask_bytes >= 2 ? 1 : 0)
-                                    + (mask_bytes >= 4 ? 1 : 0)
-                                    + (mask_bytes >= 8 ? 1 : 0)
-                                    + (mask_bytes >= 16? 1 : 0)
-                                    + 0;
-
-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
-
-  inline void init (void) {
-    mask = 0;
-  }
-
-  inline void add (hb_codepoint_t g) {
-    mask |= mask_for (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
-      mask = (mask_t) -1;
-    else {
-      mask_t ma = mask_for (a);
-      mask_t mb = mask_for (b);
-      mask |= mb + (mb - ma) - (mb < ma);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return !!(mask & mask_for (g));
-  }
-
-  private:
-
-  static inline mask_t mask_for (hb_codepoint_t g) {
-    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
-  }
-  mask_t mask;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
-  ASSERT_POD ();
-
-  inline void init (void) {
-    head.init ();
-    tail.init ();
-  }
-
-  inline void add (hb_codepoint_t g) {
-    head.add (g);
-    tail.add (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    head.add_range (a, b);
-    tail.add_range (a, b);
-    return true;
-  }
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_array (array, count, stride);
-    tail.add_array (array, count, stride);
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_sorted_array (array, count, stride);
-    tail.add_sorted_array (array, count, stride);
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return head.may_have (g) && tail.may_have (g);
-  }
-
-  private:
-  head_t head;
-  tail_t tail;
-};
-
-
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-typedef hb_set_digest_combiner_t
-<
-  hb_set_digest_lowest_bits_t<unsigned long, 4>,
-  hb_set_digest_combiner_t
-  <
-    hb_set_digest_lowest_bits_t<unsigned long, 0>,
-    hb_set_digest_lowest_bits_t<unsigned long, 9>
-  >
-> hb_set_digest_t;
-
-
-#endif /* HB_SET_DIGEST_PRIVATE_HH */
diff --git a/src/hb-set-digest.hh b/src/hb-set-digest.hh
new file mode 100644 (file)
index 0000000..b97526f
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_DIGEST_HH
+#define HB_SET_DIGEST_HH
+
+#include "hb.hh"
+
+/*
+ * The set digests here implement various "filters" that support
+ * "approximate member query".  Conceptually these are like Bloom
+ * Filter and Quotient Filter, however, much smaller, faster, and
+ * designed to fit the requirements of our uses for glyph coverage
+ * queries.
+ *
+ * Our filters are highly accurate if the lookup covers fairly local
+ * set of glyphs, but fully flooded and ineffective if coverage is
+ * all over the place.
+ *
+ * The frozen-set can be used instead of a digest, to trade more
+ * memory for 100% accuracy, but in practice, that doesn't look like
+ * an attractive trade-off.
+ */
+
+template <typename mask_t, unsigned int shift>
+struct hb_set_digest_lowest_bits_t
+{
+  static constexpr unsigned mask_bytes = sizeof (mask_t);
+  static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
+  static constexpr unsigned num_bits = 0
+                                    + (mask_bytes >= 1 ? 3 : 0)
+                                    + (mask_bytes >= 2 ? 1 : 0)
+                                    + (mask_bytes >= 4 ? 1 : 0)
+                                    + (mask_bytes >= 8 ? 1 : 0)
+                                    + (mask_bytes >= 16? 1 : 0)
+                                    + 0;
+
+  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
+  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
+
+  void init () { mask = 0; }
+
+  void add (hb_codepoint_t g) { mask |= mask_for (g); }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+      mask = (mask_t) -1;
+    else {
+      mask_t ma = mask_for (a);
+      mask_t mb = mask_for (b);
+      mask |= mb + (mb - ma) - (mb < ma);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  { return !!(mask & mask_for (g)); }
+
+  private:
+
+  static mask_t mask_for (hb_codepoint_t g)
+  { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
+  mask_t mask;
+};
+
+template <typename head_t, typename tail_t>
+struct hb_set_digest_combiner_t
+{
+  void init ()
+  {
+    head.init ();
+    tail.init ();
+  }
+
+  void add (hb_codepoint_t g)
+  {
+    head.add (g);
+    tail.add (g);
+  }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    head.add_range (a, b);
+    tail.add_range (a, b);
+    return true;
+  }
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_array (array, count, stride);
+    tail.add_array (array, count, stride);
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_sorted_array (array, count, stride);
+    tail.add_sorted_array (array, count, stride);
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  {
+    return head.may_have (g) && tail.may_have (g);
+  }
+
+  private:
+  head_t head;
+  tail_t tail;
+};
+
+
+/*
+ * hb_set_digest_t
+ *
+ * This is a combination of digests that performs "best".
+ * There is not much science to this: it's a result of intuition
+ * and testing.
+ */
+typedef hb_set_digest_combiner_t
+<
+  hb_set_digest_lowest_bits_t<unsigned long, 4>,
+  hb_set_digest_combiner_t
+  <
+    hb_set_digest_lowest_bits_t<unsigned long, 0>,
+    hb_set_digest_lowest_bits_t<unsigned long, 9>
+  >
+> hb_set_digest_t;
+
+
+#endif /* HB_SET_DIGEST_HH */
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
deleted file mode 100644 (file)
index ccd4d8d..0000000
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- * Copyright © 2012,2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_PRIVATE_HH
-#define HB_SET_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-/*
- * hb_set_t
- */
-
-/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
- * point maybe also use a sentinel value for "all-1" pages? */
-
-struct hb_set_t
-{
-  struct page_map_t
-  {
-    inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
-
-    uint32_t major;
-    uint32_t index;
-  };
-
-  struct page_t
-  {
-    inline void init0 (void) { memset (&v, 0, sizeof (v)); }
-    inline void init1 (void) { memset (&v, 0xff, sizeof (v)); }
-
-    inline unsigned int len (void) const
-    { return ARRAY_LENGTH_CONST (v); }
-
-    inline bool is_empty (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-         return false;
-      return true;
-    }
-
-    inline void add (hb_codepoint_t g) { elt (g) |= mask (g); }
-    inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
-    inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
-
-    inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
-    {
-      elt_t *la = &elt (a);
-      elt_t *lb = &elt (b);
-      if (la == lb)
-        *la |= (mask (b) << 1) - mask(a);
-      else
-      {
-       *la |= ~(mask (a) - 1);
-       la++;
-
-       memset (la, 0xff, (char *) lb - (char *) la);
-
-       *lb |= ((mask (b) << 1) - 1);
-      }
-    }
-
-    inline bool is_equal (const page_t *other) const
-    {
-      return 0 == memcmp (&v, &other->v, sizeof (v));
-    }
-
-    inline unsigned int get_population (void) const
-    {
-      unsigned int pop = 0;
-      for (unsigned int i = 0; i < len (); i++)
-        pop += _hb_popcount (v[i]);
-      return pop;
-    }
-
-    inline bool next (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint + 1) & MASK;
-      if (!m)
-      {
-       *codepoint = INVALID;
-       return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
-      for (const elt_t *p = &vv; i < len (); p = &v[++i])
-       if (*p)
-       {
-         *codepoint = i * ELT_BITS + elt_get_min (*p);
-         return true;
-       }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline bool previous (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint - 1) & MASK;
-      if (m == MASK)
-      {
-       *codepoint = INVALID;
-       return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
-      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
-       if (*p)
-       {
-         *codepoint = i * ELT_BITS + elt_get_max (*p);
-         return true;
-       }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline hb_codepoint_t get_min (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-         return i * ELT_BITS + elt_get_min (v[i]);
-      return INVALID;
-    }
-    inline hb_codepoint_t get_max (void) const
-    {
-      for (int i = len () - 1; i >= 0; i--)
-        if (v[i])
-         return i * ELT_BITS + elt_get_max (v[i]);
-      return 0;
-    }
-
-    typedef unsigned long long elt_t;
-    static const unsigned int PAGE_BITS = 512;
-    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
-
-    static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
-    static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
-
-    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
-
-    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
-    static const unsigned int ELT_MASK = ELT_BITS - 1;
-    static const unsigned int BITS = sizeof (vector_t) * 8;
-    static const unsigned int MASK = BITS - 1;
-    static_assert (PAGE_BITS == BITS, "");
-
-    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
-    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
-    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
-
-    vector_t v;
-  };
-  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  mutable unsigned int population;
-  hb_vector_t<page_map_t, 1> page_map;
-  hb_vector_t<page_t, 1> pages;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = 0;
-    page_map.init ();
-    pages.init ();
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    page_map.fini ();
-    pages.fini ();
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (unsigned int count)
-  {
-    if (unlikely (!successful)) return false;
-    if (!pages.resize (count) || !page_map.resize (count))
-    {
-      pages.resize (page_map.len);
-      successful = false;
-      return false;
-    }
-    return true;
-  }
-
-  inline void clear (void) {
-    if (unlikely (hb_object_is_inert (this)))
-      return;
-    successful = true;
-    population = 0;
-    page_map.resize (0);
-    pages.resize (0);
-  }
-  inline bool is_empty (void) const {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!pages[i].is_empty ())
-        return false;
-    return true;
-  }
-
-  inline void dirty (void) { population = (unsigned int) -1; }
-
-  inline void add (hb_codepoint_t g)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (g == INVALID)) return;
-    dirty ();
-    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-    page->add (g);
-  }
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
-    dirty ();
-    unsigned int ma = get_major (a);
-    unsigned int mb = get_major (b);
-    if (ma == mb)
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, b);
-    }
-    else
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, major_start (ma + 1) - 1);
-
-      for (unsigned int m = ma + 1; m < mb; m++)
-      {
-       page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
-       page->init1 ();
-      }
-
-      page = page_for_insert (b); if (unlikely (!page)) return false;
-      page->add_range (major_start (mb), b);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return;
-    if (!count) return;
-    dirty ();
-    hb_codepoint_t g = *array;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-      unsigned int start = major_start (m);
-      unsigned int end = major_start (m + 1);
-      do
-      {
-       page->add (g);
-
-       array = (const T *) ((const char *) array + stride);
-       count--;
-      }
-      while (count && (g = *array, start <= g && g < end));
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (!count) return true;
-    dirty ();
-    hb_codepoint_t g = *array;
-    hb_codepoint_t last_g = g;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        /* If we try harder we can change the following comparison to <=;
-        * Not sure if it's worth it. */
-        if (g < last_g) return false;
-       last_g = g;
-       page->add (g);
-
-       array = (const T *) ((const char *) array + stride);
-       count--;
-      }
-      while (count && (g = *array, g < end));
-    }
-    return true;
-  }
-
-  inline void del (hb_codepoint_t g)
-  {
-    /* TODO perform op even if !successful. */
-    if (unlikely (!successful)) return;
-    page_t *p = page_for (g);
-    if (!p)
-      return;
-    dirty ();
-    p->del (g);
-  }
-  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    /* TODO perform op even if !successful. */
-    /* TODO Optimize, like add_range(). */
-    if (unlikely (!successful)) return;
-    for (unsigned int i = a; i < b + 1; i++)
-      del (i);
-  }
-  inline bool has (hb_codepoint_t g) const
-  {
-    const page_t *p = page_for (g);
-    if (!p)
-      return false;
-    return p->has (g);
-  }
-  inline bool intersects (hb_codepoint_t first,
-                         hb_codepoint_t last) const
-  {
-    hb_codepoint_t c = first - 1;
-    return next (&c) && c <= last;
-  }
-  inline void set (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-    unsigned int count = other->pages.len;
-    if (!resize (count))
-      return;
-    population = other->population;
-    memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0]));
-    memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0]));
-  }
-
-  inline bool is_equal (const hb_set_t *other) const
-  {
-    if (get_population () != other->get_population ())
-      return false;
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_at (a).is_empty ()) { a++; continue; }
-      if (other->page_at (b).is_empty ()) { b++; continue; }
-      if (page_map[a].major != other->page_map[b].major ||
-         !page_at (a).is_equal (&other->page_at (b)))
-        return false;
-      a++;
-      b++;
-    }
-    for (; a < na; a++)
-      if (!page_at (a).is_empty ()) { return false; }
-    for (; b < nb; b++)
-      if (!other->page_at (b).is_empty ()) { return false; }
-
-    return true;
-  }
-
-  inline bool is_subset (const hb_set_t *larger_set) const
-  {
-    if (get_population () > larger_set->get_population ())
-      return false;
-
-    hb_codepoint_t c = INVALID;
-    while (next (&c))
-      if (!larger_set->has (c))
-        return false;
-
-    return true;
-  }
-
-  template <class Op>
-  inline void process (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-
-    dirty ();
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-    unsigned int next_page = na;
-
-    unsigned int count = 0, newCount = 0;
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_map[a].major == other->page_map[b].major)
-      {
-        count++;
-       a++;
-       b++;
-      }
-      else if (page_map[a].major < other->page_map[b].major)
-      {
-        if (Op::passthru_left)
-         count++;
-        a++;
-      }
-      else
-      {
-        if (Op::passthru_right)
-         count++;
-        b++;
-      }
-    }
-    if (Op::passthru_left)
-      count += na - a;
-    if (Op::passthru_right)
-      count += nb - b;
-
-    if (count > pages.len)
-      if (!resize (count))
-        return;
-    newCount = count;
-
-    /* Process in-place backward. */
-    a = na;
-    b = nb;
-    for (; a && b; )
-    {
-      if (page_map[a - 1].major == other->page_map[b - 1].major)
-      {
-       a--;
-       b--;
-       count--;
-       page_map[count] = page_map[a];
-       Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
-      }
-      else if (page_map[a - 1].major > other->page_map[b - 1].major)
-      {
-       a--;
-       if (Op::passthru_left)
-       {
-         count--;
-         page_map[count] = page_map[a];
-       }
-      }
-      else
-      {
-       b--;
-       if (Op::passthru_right)
-       {
-         count--;
-         page_map[count].major = other->page_map[b].major;
-         page_map[count].index = next_page++;
-         page_at (count).v = other->page_at (b).v;
-       }
-      }
-    }
-    if (Op::passthru_left)
-      while (a)
-      {
-       a--;
-       count--;
-       page_map[count] = page_map [a];
-      }
-    if (Op::passthru_right)
-      while (b)
-      {
-       b--;
-       count--;
-       page_map[count].major = other->page_map[b].major;
-       page_map[count].index = next_page++;
-       page_at (count).v = other->page_at (b).v;
-      }
-    assert (!count);
-    if (pages.len > newCount)
-      resize (newCount);
-  }
-
-  inline void union_ (const hb_set_t *other)
-  {
-    process<HbOpOr> (other);
-  }
-  inline void intersect (const hb_set_t *other)
-  {
-    process<HbOpAnd> (other);
-  }
-  inline void subtract (const hb_set_t *other)
-  {
-    process<HbOpMinus> (other);
-  }
-  inline void symmetric_difference (const hb_set_t *other)
-  {
-    process<HbOpXor> (other);
-  }
-  inline bool next (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_min ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].next (codepoint))
-      {
-       *codepoint += page_map[i].major * page_t::PAGE_BITS;
-       return true;
-      }
-      i++;
-    }
-    for (; i < page_map.len; i++)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_min ();
-      if (m != INVALID)
-      {
-       *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-       return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool previous (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_max ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].previous (codepoint))
-      {
-       *codepoint += page_map[i].major * page_t::PAGE_BITS;
-       return true;
-      }
-    }
-    i--;
-    for (; (int) i >= 0; i--)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_max ();
-      if (m != INVALID)
-      {
-       *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-       return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *last;
-    if (!next (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (next (&i) && i == *last + 1)
-      (*last)++;
-
-    return true;
-  }
-  inline bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *first;
-    if (!previous (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (previous (&i) && i == *first - 1)
-      (*first)--;
-
-    return true;
-  }
-
-  inline unsigned int get_population (void) const
-  {
-    if (population != (unsigned int) -1)
-      return population;
-
-    unsigned int pop = 0;
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      pop += pages[i].get_population ();
-
-    population = pop;
-    return pop;
-  }
-  inline hb_codepoint_t get_min (void) const
-  {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
-    return INVALID;
-  }
-  inline hb_codepoint_t get_max (void) const
-  {
-    unsigned int count = pages.len;
-    for (int i = count - 1; i >= 0; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max ();
-    return INVALID;
-  }
-
-  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
-
-  inline page_t *page_for_insert (hb_codepoint_t g)
-  {
-    page_map_t map = {get_major (g), pages.len};
-    unsigned int i;
-    if (!page_map.bfind (map, &i))
-    {
-      if (!resize (pages.len + 1))
-       return nullptr;
-
-      pages[map.index].init0 ();
-      memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0]));
-      page_map[i] = map;
-    }
-    return &pages[page_map[i].index];
-  }
-  inline page_t *page_for (hb_codepoint_t g)
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline const page_t *page_for (hb_codepoint_t g) const
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
-  inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
-  inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
-};
-
-
-#endif /* HB_SET_PRIVATE_HH */
index 25027e6..0682362 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-set-private.hh"
+#include "hb-set.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-set
+ * @title: hb-set
+ * @short_description: Object representing a set of integers
+ * @include: hb.h
+ *
+ * Set objects represent a mathematical set of integer values.  They are
+ * used in non-shaping API to query certain set of characters or glyphs,
+ * or other integer values.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_create (void)
+hb_set_create ()
 {
   hb_set_t *set;
 
@@ -58,7 +67,7 @@ hb_set_create (void)
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_get_empty (void)
+hb_set_get_empty ()
 {
   return const_cast<hb_set_t *> (&Null(hb_set_t));
 }
@@ -391,7 +400,7 @@ hb_set_symmetric_difference (hb_set_t       *set,
  * Deprecated: 1.6.1
  **/
 void
-hb_set_invert (hb_set_t *set)
+hb_set_invert (hb_set_t *set HB_UNUSED)
 {
 }
 
diff --git a/src/hb-set.hh b/src/hb-set.hh
new file mode 100644 (file)
index 0000000..64a1363
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * Copyright © 2012,2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_HH
+#define HB_SET_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_set_t
+ */
+
+/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
+ * point maybe also use a sentinel value for "all-1" pages? */
+
+struct hb_set_t
+{
+  HB_NO_COPY_ASSIGN (hb_set_t);
+  hb_set_t ()  { init (); }
+  ~hb_set_t () { fini (); }
+
+  struct page_map_t
+  {
+    int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
+
+    uint32_t major;
+    uint32_t index;
+  };
+
+  struct page_t
+  {
+    void init0 () { v.clear (); }
+    void init1 () { v.clear (0xFF); }
+
+    unsigned int len () const
+    { return ARRAY_LENGTH_CONST (v); }
+
+    bool is_empty () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+         return false;
+      return true;
+    }
+
+    void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+    void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+    bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
+
+    void add_range (hb_codepoint_t a, hb_codepoint_t b)
+    {
+      elt_t *la = &elt (a);
+      elt_t *lb = &elt (b);
+      if (la == lb)
+        *la |= (mask (b) << 1) - mask(a);
+      else
+      {
+       *la |= ~(mask (a) - 1);
+       la++;
+
+       memset (la, 0xff, (char *) lb - (char *) la);
+
+       *lb |= ((mask (b) << 1) - 1);
+      }
+    }
+
+    bool is_equal (const page_t *other) const
+    {
+      return 0 == hb_memcmp (&v, &other->v, sizeof (v));
+    }
+
+    unsigned int get_population () const
+    {
+      unsigned int pop = 0;
+      for (unsigned int i = 0; i < len (); i++)
+        pop += hb_popcount (v[i]);
+      return pop;
+    }
+
+    bool next (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint + 1) & MASK;
+      if (!m)
+      {
+       *codepoint = INVALID;
+       return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
+      for (const elt_t *p = &vv; i < len (); p = &v[++i])
+       if (*p)
+       {
+         *codepoint = i * ELT_BITS + elt_get_min (*p);
+         return true;
+       }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    bool previous (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint - 1) & MASK;
+      if (m == MASK)
+      {
+       *codepoint = INVALID;
+       return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
+      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
+       if (*p)
+       {
+         *codepoint = i * ELT_BITS + elt_get_max (*p);
+         return true;
+       }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    hb_codepoint_t get_min () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+         return i * ELT_BITS + elt_get_min (v[i]);
+      return INVALID;
+    }
+    hb_codepoint_t get_max () const
+    {
+      for (int i = len () - 1; i >= 0; i--)
+        if (v[i])
+         return i * ELT_BITS + elt_get_max (v[i]);
+      return 0;
+    }
+
+    typedef unsigned long long elt_t;
+    static constexpr unsigned PAGE_BITS = 512;
+    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+
+    static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
+    static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
+
+    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
+
+    static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+    static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+    static constexpr unsigned BITS = sizeof (vector_t) * 8;
+    static constexpr unsigned MASK = BITS - 1;
+    static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
+
+    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
+    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
+    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
+
+    vector_t v;
+  };
+  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  mutable unsigned int population;
+  hb_vector_t<page_map_t> page_map;
+  hb_vector_t<page_t> pages;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = 0;
+    page_map.init ();
+    pages.init ();
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    population = 0;
+    page_map.fini ();
+    pages.fini ();
+  }
+  void fini ()
+  {
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize (unsigned int count)
+  {
+    if (unlikely (!successful)) return false;
+    if (!pages.resize (count) || !page_map.resize (count))
+    {
+      pages.resize (page_map.length);
+      successful = false;
+      return false;
+    }
+    return true;
+  }
+
+  void clear ()
+  {
+    if (unlikely (hb_object_is_immutable (this)))
+      return;
+    successful = true;
+    population = 0;
+    page_map.resize (0);
+    pages.resize (0);
+  }
+  bool is_empty () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!pages[i].is_empty ())
+        return false;
+    return true;
+  }
+
+  void dirty () { population = (unsigned int) -1; }
+
+  void add (hb_codepoint_t g)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (g == INVALID)) return;
+    dirty ();
+    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+    page->add (g);
+  }
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
+    dirty ();
+    unsigned int ma = get_major (a);
+    unsigned int mb = get_major (b);
+    if (ma == mb)
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, major_start (ma + 1) - 1);
+
+      for (unsigned int m = ma + 1; m < mb; m++)
+      {
+       page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
+       page->init1 ();
+      }
+
+      page = page_for_insert (b); if (unlikely (!page)) return false;
+      page->add_range (major_start (mb), b);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return;
+    if (!count) return;
+    dirty ();
+    hb_codepoint_t g = *array;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+       page->add (g);
+
+       array = (const T *) ((const char *) array + stride);
+       count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (!count) return true;
+    dirty ();
+    hb_codepoint_t g = *array;
+    hb_codepoint_t last_g = g;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        /* If we try harder we can change the following comparison to <=;
+        * Not sure if it's worth it. */
+        if (g < last_g) return false;
+       last_g = g;
+       page->add (g);
+
+       array = (const T *) ((const char *) array + stride);
+       count--;
+      }
+      while (count && (g = *array, g < end));
+    }
+    return true;
+  }
+
+  void del (hb_codepoint_t g)
+  {
+    /* TODO perform op even if !successful. */
+    if (unlikely (!successful)) return;
+    page_t *page = page_for (g);
+    if (!page)
+      return;
+    dirty ();
+    page->del (g);
+  }
+  void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    /* TODO perform op even if !successful. */
+    /* TODO Optimize, like add_range(). */
+    if (unlikely (!successful)) return;
+    for (unsigned int i = a; i < b + 1; i++)
+      del (i);
+  }
+  bool has (hb_codepoint_t g) const
+  {
+    const page_t *page = page_for (g);
+    if (!page)
+      return false;
+    return page->has (g);
+  }
+  bool intersects (hb_codepoint_t first,
+                         hb_codepoint_t last) const
+  {
+    hb_codepoint_t c = first - 1;
+    return next (&c) && c <= last;
+  }
+  void set (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+    unsigned int count = other->pages.length;
+    if (!resize (count))
+      return;
+    population = other->population;
+    memcpy ((void *) pages, (const void *) other->pages, count * pages.item_size);
+    memcpy ((void *) page_map, (const void *) other->page_map, count * page_map.item_size);
+  }
+
+  bool is_equal (const hb_set_t *other) const
+  {
+    if (get_population () != other->get_population ())
+      return false;
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_at (a).is_empty ()) { a++; continue; }
+      if (other->page_at (b).is_empty ()) { b++; continue; }
+      if (page_map[a].major != other->page_map[b].major ||
+         !page_at (a).is_equal (&other->page_at (b)))
+        return false;
+      a++;
+      b++;
+    }
+    for (; a < na; a++)
+      if (!page_at (a).is_empty ()) { return false; }
+    for (; b < nb; b++)
+      if (!other->page_at (b).is_empty ()) { return false; }
+
+    return true;
+  }
+
+  bool is_subset (const hb_set_t *larger_set) const
+  {
+    if (get_population () > larger_set->get_population ())
+      return false;
+
+    /* TODO Optimize to use pages. */
+    hb_codepoint_t c = INVALID;
+    while (next (&c))
+      if (!larger_set->has (c))
+        return false;
+
+    return true;
+  }
+
+  template <class Op>
+  void process (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+
+    dirty ();
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+    unsigned int next_page = na;
+
+    unsigned int count = 0, newCount = 0;
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_map[a].major == other->page_map[b].major)
+      {
+        count++;
+       a++;
+       b++;
+      }
+      else if (page_map[a].major < other->page_map[b].major)
+      {
+        if (Op::passthru_left)
+         count++;
+        a++;
+      }
+      else
+      {
+        if (Op::passthru_right)
+         count++;
+        b++;
+      }
+    }
+    if (Op::passthru_left)
+      count += na - a;
+    if (Op::passthru_right)
+      count += nb - b;
+
+    if (count > pages.length)
+      if (!resize (count))
+        return;
+    newCount = count;
+
+    /* Process in-place backward. */
+    a = na;
+    b = nb;
+    for (; a && b; )
+    {
+      if (page_map[a - 1].major == other->page_map[b - 1].major)
+      {
+       a--;
+       b--;
+       count--;
+       page_map[count] = page_map[a];
+       Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
+      }
+      else if (page_map[a - 1].major > other->page_map[b - 1].major)
+      {
+       a--;
+       if (Op::passthru_left)
+       {
+         count--;
+         page_map[count] = page_map[a];
+       }
+      }
+      else
+      {
+       b--;
+       if (Op::passthru_right)
+       {
+         count--;
+         page_map[count].major = other->page_map[b].major;
+         page_map[count].index = next_page++;
+         page_at (count).v = other->page_at (b).v;
+       }
+      }
+    }
+    if (Op::passthru_left)
+      while (a)
+      {
+       a--;
+       count--;
+       page_map[count] = page_map [a];
+      }
+    if (Op::passthru_right)
+      while (b)
+      {
+       b--;
+       count--;
+       page_map[count].major = other->page_map[b].major;
+       page_map[count].index = next_page++;
+       page_at (count).v = other->page_at (b).v;
+      }
+    assert (!count);
+    if (pages.length > newCount)
+      resize (newCount);
+  }
+
+  void union_ (const hb_set_t *other)
+  {
+    process<HbOpOr> (other);
+  }
+  void intersect (const hb_set_t *other)
+  {
+    process<HbOpAnd> (other);
+  }
+  void subtract (const hb_set_t *other)
+  {
+    process<HbOpMinus> (other);
+  }
+  void symmetric_difference (const hb_set_t *other)
+  {
+    process<HbOpXor> (other);
+  }
+  bool next (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_min ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].next (codepoint))
+      {
+       *codepoint += page_map[i].major * page_t::PAGE_BITS;
+       return true;
+      }
+      i++;
+    }
+    for (; i < page_map.length; i++)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_min ();
+      if (m != INVALID)
+      {
+       *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+       return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool previous (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_max ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].previous (codepoint))
+      {
+       *codepoint += page_map[i].major * page_t::PAGE_BITS;
+       return true;
+      }
+    }
+    i--;
+    for (; (int) i >= 0; i--)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_max ();
+      if (m != INVALID)
+      {
+       *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+       return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *last;
+    if (!next (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (next (&i) && i == *last + 1)
+      (*last)++;
+
+    return true;
+  }
+  bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *first;
+    if (!previous (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (previous (&i) && i == *first - 1)
+      (*first)--;
+
+    return true;
+  }
+
+  unsigned int get_population () const
+  {
+    if (population != (unsigned int) -1)
+      return population;
+
+    unsigned int pop = 0;
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      pop += pages[i].get_population ();
+
+    population = pop;
+    return pop;
+  }
+  hb_codepoint_t get_min () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
+    return INVALID;
+  }
+  hb_codepoint_t get_max () const
+  {
+    unsigned int count = pages.length;
+    for (int i = count - 1; i >= 0; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
+    return INVALID;
+  }
+
+  static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
+
+  /*
+   * Iterator implementation.
+   */
+  struct const_iter_t : hb_sorted_iter_t<const_iter_t, const hb_codepoint_t>
+  {
+    const_iter_t (const hb_set_t &s_) :
+      s (s_), v (INVALID), l (s.get_population () + 1) { __next__ (); }
+
+    typedef hb_codepoint_t __item_type__;
+    hb_codepoint_t __item__ () const { return v; }
+    bool __more__ () const { return v != INVALID; }
+    void __next__ () { s.next (&v); if (l) l--; }
+    void __prev__ () { s.previous (&v); }
+    unsigned __len__ () { return l; }
+
+    protected:
+    const hb_set_t &s;
+    hb_codepoint_t v;
+    unsigned l;
+  };
+  const_iter_t const_iter () const { return const_iter_t (*this); }
+  operator const_iter_t () const { return const_iter (); }
+  typedef const_iter_t iter_t;
+  iter_t iter () const { return const_iter (); }
+
+  protected:
+
+  page_t *page_for_insert (hb_codepoint_t g)
+  {
+    page_map_t map = {get_major (g), pages.length};
+    unsigned int i;
+    if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
+    {
+      if (!resize (pages.length + 1))
+       return nullptr;
+
+      pages[map.index].init0 ();
+      memmove (page_map + i + 1,
+              page_map + i,
+              (page_map.length - 1 - i) * page_map.item_size);
+      page_map[i] = map;
+    }
+    return &pages[page_map[i].index];
+  }
+  page_t *page_for (hb_codepoint_t g)
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  const page_t *page_for (hb_codepoint_t g) const
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
+  const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
+  unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
+  hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+};
+
+
+#endif /* HB_SET_HH */
diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh
deleted file mode 100644 (file)
index aa0413a..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPE_PLAN_PRIVATE_HH
-#define HB_SHAPE_PLAN_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-
-
-struct hb_shape_plan_t
-{
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t default_shaper_list;
-  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-  hb_segment_properties_t props;
-
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
-
-  hb_feature_t *user_features;
-  unsigned int num_user_features;
-
-  int *coords;
-  unsigned int num_coords;
-
-  struct hb_shaper_data_t shaper_data;
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
-       , const hb_feature_t *user_features \
-       , unsigned int        num_user_features \
-       , const int          *coords \
-       , unsigned int        num_coords
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_SHAPE_PLAN_PRIVATE_HH */
index 6eeba2b..61ea8d0 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-static void
-hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
-                   const hb_feature_t *user_features,
-                   unsigned int        num_user_features,
-                   const int          *coords,
-                   unsigned int        num_coords,
-                   const char * const *shaper_list)
+#include "hb.hh"
+#include "hb-shape-plan.hh"
+#include "hb-shaper.hh"
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+
+
+/**
+ * SECTION:hb-shape-plan
+ * @title: hb-shape-plan
+ * @short_description: Object representing a shaping plan
+ * @include: hb.h
+ *
+ * Shape plans are not used for shaping directly, but can be access to query
+ * certain information about how shaping will perform given a set of input
+ * parameters (script, language, direction, features, etc.)
+ * Most client would not need to deal with shape plans directly.
+ **/
+
+
+/*
+ * hb_shape_plan_key_t
+ */
+
+bool
+hb_shape_plan_key_t::init (bool                           copy,
+                          hb_face_t                     *face,
+                          const hb_segment_properties_t *props,
+                          const hb_feature_t            *user_features,
+                          unsigned int                   num_user_features,
+                          const int                     *coords,
+                          unsigned int                   num_coords,
+                          const char * const            *shaper_list)
 {
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-                 "num_features=%d num_coords=%d shaper_list=%p",
-                 num_user_features,
-                 num_coords,
-                 shaper_list);
+  hb_feature_t *features = nullptr;
+  if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
+    goto bail;
+
+  this->props = *props;
+  this->num_user_features = num_user_features;
+  this->user_features = copy ? features : user_features;
+  if (copy && num_user_features)
+  {
+    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+    /* Make start/end uniform to easier catch bugs. */
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      if (features[0].start != HB_FEATURE_GLOBAL_START)
+       features[0].start = 1;
+      if (features[0].end   != HB_FEATURE_GLOBAL_END)
+       features[0].end   = 2;
+    }
+  }
+  this->shaper_func = nullptr;
+  this->shaper_name = nullptr;
+  this->ot.init (face, coords, num_coords);
 
-  const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+  /*
+   * Choose shaper.
+   */
 
 #define HB_SHAPER_PLAN(shaper) \
        HB_STMT_START { \
-         if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
-           HB_SHAPER_DATA (shaper, shape_plan) = \
-             HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
-                                                              user_features, num_user_features, \
-                                                              coords, num_coords); \
-           shape_plan->shaper_func = _hb_##shaper##_shape; \
-           shape_plan->shaper_name = #shaper; \
-           return; \
+         if (face->data.shaper) \
+         { \
+           this->shaper_func = _hb_##shaper##_shape; \
+           this->shaper_name = #shaper; \
+           return true; \
          } \
        } HB_STMT_END
 
-  if (likely (!shaper_list)) {
-    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-      if (0)
+  if (unlikely (shaper_list))
+  {
+    for (; *shaper_list; shaper_list++)
+      if (false)
        ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (shapers[i].func == _hb_##shaper##_shape) \
+      else if (0 == strcmp (*shaper_list, #shaper)) \
        HB_SHAPER_PLAN (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
-  } else {
-    for (; *shaper_list; shaper_list++)
-      if (0)
+  }
+  else
+  {
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+      if (false)
        ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_list, #shaper)) \
+      else if (shapers[i].func == _hb_##shaper##_shape) \
        HB_SHAPER_PLAN (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   }
-
 #undef HB_SHAPER_PLAN
+
+bail:
+  ::free (features);
+  return false;
+}
+
+bool
+hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other)
+{
+  if (this->num_user_features != other->num_user_features)
+    return false;
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
+    if (this->user_features[i].tag   != other->user_features[i].tag   ||
+       this->user_features[i].value != other->user_features[i].value ||
+       (this->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+        this->user_features[i].end   == HB_FEATURE_GLOBAL_END) !=
+       (other->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+        other->user_features[i].end   == HB_FEATURE_GLOBAL_END))
+      return false;
+  }
+  return true;
+}
+
+bool
+hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
+{
+  return hb_segment_properties_equal (&this->props, &other->props) &&
+        this->user_features_match (other) &&
+        this->ot.equal (&other->ot) &&
+        this->shaper_func == other->shaper_func;
 }
 
 
@@ -89,6 +157,7 @@ hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
  * hb_shape_plan_t
  */
 
+
 /**
  * hb_shape_plan_create: (Xconstructor)
  * @face: 
@@ -121,7 +190,7 @@ hb_shape_plan_create2 (hb_face_t                     *face,
                       const hb_segment_properties_t *props,
                       const hb_feature_t            *user_features,
                       unsigned int                   num_user_features,
-                      const int                     *orig_coords,
+                      const int                     *coords,
                       unsigned int                   num_coords,
                       const char * const            *shaper_list)
 {
@@ -132,49 +201,40 @@ hb_shape_plan_create2 (hb_face_t                     *face,
                  num_coords,
                  shaper_list);
 
+  assert (props->direction != HB_DIRECTION_INVALID);
+
   hb_shape_plan_t *shape_plan;
-  hb_feature_t *features = nullptr;
-  int *coords = nullptr;
 
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
   if (unlikely (!props))
-    return hb_shape_plan_get_empty ();
-  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
-    return hb_shape_plan_get_empty ();
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-  {
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
+    goto bail;
   if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
-  {
-    free (coords);
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-
-  assert (props->direction != HB_DIRECTION_INVALID);
+    goto bail;
 
+  if (unlikely (!face))
+    face = hb_face_get_empty ();
   hb_face_make_immutable (face);
-  shape_plan->default_shaper_list = !shaper_list;
   shape_plan->face_unsafe = face;
-  shape_plan->props = *props;
-  shape_plan->num_user_features = num_user_features;
-  shape_plan->user_features = features;
-  if (num_user_features)
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
 
-  hb_shape_plan_plan (shape_plan,
-                     user_features, num_user_features,
-                     coords, num_coords,
-                     shaper_list);
+  if (unlikely (!shape_plan->key.init (true,
+                                      face,
+                                      props,
+                                      user_features,
+                                      num_user_features,
+                                      coords,
+                                      num_coords,
+                                      shaper_list)))
+    goto bail2;
+  if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key)))
+    goto bail3;
 
   return shape_plan;
+
+bail3:
+  shape_plan->key.free ();
+bail2:
+  free (shape_plan);
+bail:
+  return hb_shape_plan_get_empty ();
 }
 
 /**
@@ -187,32 +247,9 @@ hb_shape_plan_create2 (hb_face_t                     *face,
  * Since: 0.9.7
  **/
 hb_shape_plan_t *
-hb_shape_plan_get_empty (void)
+hb_shape_plan_get_empty ()
 {
-  static const hb_shape_plan_t _hb_shape_plan_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* default_shaper_list */
-    nullptr, /* face */
-    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
-    nullptr, /* shaper_func */
-    nullptr, /* shaper_name */
-
-    nullptr, /* user_features */
-    0,    /* num_user_featurs */
-
-    nullptr, /* coords */
-    0,    /* num_coords */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
+  return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
 }
 
 /**
@@ -244,13 +281,8 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
 {
   if (!hb_object_destroy (shape_plan)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  free (shape_plan->user_features);
-  free (shape_plan->coords);
-
+  shape_plan->ot.fini ();
+  shape_plan->key.free ();
   free (shape_plan);
 }
 
@@ -296,6 +328,22 @@ hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
   return hb_object_get_user_data (shape_plan, key);
 }
 
+/**
+ * hb_shape_plan_get_shaper:
+ * @shape_plan: a shape plan.
+ *
+ * 
+ *
+ * Return value: (transfer none):
+ *
+ * Since: 0.9.7
+ **/
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
+{
+  return shape_plan->key.shaper_name;
+}
+
 
 /**
  * hb_shape_plan_execute:
@@ -321,32 +369,31 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
                  "num_features=%d shaper_func=%p, shaper_name=%s",
                  num_features,
-                 shape_plan->shaper_func,
-                 shape_plan->shaper_name);
+                 shape_plan->key.shaper_func,
+                 shape_plan->key.shaper_name);
 
   if (unlikely (!buffer->len))
     return true;
 
-  assert (!hb_object_is_inert (buffer));
+  assert (!hb_object_is_immutable (buffer));
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
 
   if (unlikely (hb_object_is_inert (shape_plan)))
     return false;
 
   assert (shape_plan->face_unsafe == font->face);
-  assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
+  assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
 
 #define HB_SHAPER_EXECUTE(shaper) \
        HB_STMT_START { \
-         return HB_SHAPER_DATA (shaper, shape_plan) && \
-                hb_##shaper##_shaper_font_data_ensure (font) && \
+         return font->data.shaper && \
                 _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
        } HB_STMT_END
 
-  if (0)
+  if (false)
     ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-  else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
+  else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
     HB_SHAPER_EXECUTE (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
@@ -358,91 +405,8 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
 
 
 /*
- * caching
- */
-
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
-  return hb_segment_properties_hash (&shape_plan->props) +
-        shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
-}
-#endif
-
-/* User-feature caching is currently somewhat dumb:
- * it only finds matches where the feature array is identical,
- * not cases where the feature lists would be compatible for plan purposes
- * but have different ranges, for example.
+ * Caching
  */
-struct hb_shape_plan_proposal_t
-{
-  const hb_segment_properties_t  props;
-  const char * const            *shaper_list;
-  const hb_feature_t            *user_features;
-  unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
-  hb_shape_func_t               *shaper_func;
-};
-
-static inline hb_bool_t
-hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
-                                  const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_user_features != shape_plan->num_user_features)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
-    if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
-        proposal->user_features[i].value != shape_plan->user_features[i].value ||
-        proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
-}
-
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-                           const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_coords != shape_plan->num_coords)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
-  return true;
-}
-
-static hb_bool_t
-hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
-                      const hb_shape_plan_proposal_t *proposal)
-{
-  return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
-        hb_shape_plan_user_features_match (shape_plan, proposal) &&
-        hb_shape_plan_coords_match (shape_plan, proposal) &&
-        ((shape_plan->default_shaper_list && !proposal->shaper_list) ||
-         (shape_plan->shaper_func == proposal->shaper_func));
-}
-
-static inline hb_bool_t
-hb_non_global_user_features_present (const hb_feature_t *user_features,
-                                    unsigned int        num_user_features)
-{
-  while (num_user_features) {
-    if (user_features->start != 0 || user_features->end != (unsigned int) -1)
-      return true;
-    num_user_features--;
-    user_features++;
-  }
-  return false;
-}
-
-static inline hb_bool_t
-hb_coords_present (const int *coords,
-                  unsigned int num_coords)
-{
-  return num_coords != 0;
-}
 
 /**
  * hb_shape_plan_create_cached:
@@ -486,62 +450,38 @@ hb_shape_plan_create_cached2 (hb_face_t                     *face,
                  num_user_features,
                  shaper_list);
 
-  hb_shape_plan_proposal_t proposal = {
-    *props,
-    shaper_list,
-    user_features,
-    num_user_features,
-    nullptr
-  };
-
-  if (shaper_list) {
-    /* Choose shaper.  Adapted from hb_shape_plan_plan().
-     * Must choose shaper exactly the same way as that function. */
-    for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
-      if (0)
-       ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_item, #shaper) && \
-              hb_##shaper##_shaper_face_data_ensure (face)) \
-      { \
-       proposal.shaper_func = _hb_##shaper##_shape; \
-       break; \
-      }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-    if (unlikely (!proposal.shaper_func))
-      return hb_shape_plan_get_empty ();
-  }
+retry:
+  hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
 
+  bool dont_cache = hb_object_is_inert (face);
 
-retry:
-  hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
+  if (likely (!dont_cache))
+  {
+    hb_shape_plan_key_t key;
+    if (!key.init (false,
+                  face,
+                  props,
+                  user_features,
+                  num_user_features,
+                  coords,
+                  num_coords,
+                  shaper_list))
+      return hb_shape_plan_get_empty ();
 
-  /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
-  if (!hb_coords_present (coords, num_coords))
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
-      if (hb_shape_plan_matches (node->shape_plan, &proposal))
+      if (node->shape_plan->key.equal (&key))
       {
         DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
         return hb_shape_plan_reference (node->shape_plan);
       }
+  }
 
-  /* Not found. */
   hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
                                                       user_features, num_user_features,
                                                       coords, num_coords,
                                                       shaper_list);
 
-  /* Don't add to the cache if face is inert. */
-  if (unlikely (hb_object_is_inert (face)))
-    return shape_plan;
-
-  /* Don't add the plan to the cache if there were user features with non-global ranges */
-  if (hb_non_global_user_features_present (user_features, num_user_features))
-    return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
+  if (unlikely (dont_cache))
     return shape_plan;
 
   hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
@@ -551,7 +491,8 @@ retry:
   node->shape_plan = shape_plan;
   node->next = cached_plan_nodes;
 
-  if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) {
+  if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node)))
+  {
     hb_shape_plan_destroy (shape_plan);
     free (node);
     goto retry;
@@ -560,19 +501,3 @@ retry:
 
   return hb_shape_plan_reference (shape_plan);
 }
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
-  return shape_plan->shaper_name;
-}
diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh
new file mode 100644 (file)
index 0000000..3a057fd
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPE_PLAN_HH
+#define HB_SHAPE_PLAN_HH
+
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-ot-shape.hh"
+
+
+struct hb_shape_plan_key_t
+{
+  hb_segment_properties_t  props;
+
+  const hb_feature_t      *user_features;
+  unsigned int             num_user_features;
+
+  hb_ot_shape_plan_key_t   ot;
+
+  hb_shape_func_t         *shaper_func;
+  const char              *shaper_name;
+
+  HB_INTERNAL inline bool init (bool                           copy,
+                               hb_face_t                     *face,
+                               const hb_segment_properties_t *props,
+                               const hb_feature_t            *user_features,
+                               unsigned int                   num_user_features,
+                               const int                     *coords,
+                               unsigned int                   num_coords,
+                               const char * const            *shaper_list);
+
+  HB_INTERNAL inline void free () { ::free ((void *) user_features); }
+
+  HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
+
+  HB_INTERNAL bool equal (const hb_shape_plan_key_t *other);
+};
+
+struct hb_shape_plan_t
+{
+  hb_object_header_t header;
+  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
+  hb_shape_plan_key_t key;
+  hb_ot_shape_plan_t ot;
+};
+
+
+#endif /* HB_SHAPE_PLAN_HH */
index c1e7365..deff77b 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
 
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-font-private.hh"
 
 /**
  * SECTION:hb-shape
- * @title: Shaping
+ * @title: hb-shape
  * @short_description: Conversion of text strings into positioned glyphs
  * @include: hb.h
  *
  * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
  * which are sequences of Unicode characters that use the same font and have
- * the same text direction, script and language. After shaping the buffer
+ * the same text direction, script, and language. After shaping the buffer
  * contains the output glyphs and their positions.
  **/
 
-static const char **static_shaper_list;
 
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shaper_list (void)
+#if HB_USE_ATEXIT
+static void free_static_shaper_list ();
+#endif
+
+static const char *nil_shaper_list[] = {nullptr};
+
+static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+                                                             hb_shaper_list_lazy_loader_t>
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-  if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
-    goto retry;
+  static const char ** create ()
+  {
+    const char **shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
+    if (unlikely (!shaper_list))
+      return nullptr;
+
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    unsigned int i;
+    for (i = 0; i < HB_SHAPERS_COUNT; i++)
+      shaper_list[i] = shapers[i].name;
+    shaper_list[i] = nullptr;
+
+#if HB_USE_ATEXIT
+    atexit (free_static_shaper_list);
+#endif
+
+    return shaper_list;
+  }
+  static void destroy (const char **l)
+  { free (l); }
+  static const char ** get_null ()
+  { return nil_shaper_list; }
+} static_shaper_list;
 
-  free (shaper_list);
+#if HB_USE_ATEXIT
+static
+void free_static_shaper_list ()
+{
+  static_shaper_list.free_instance ();
 }
 #endif
 
+
 /**
  * hb_shape_list_shapers:
  *
@@ -71,37 +101,9 @@ retry:
  * Since: 0.9.2
  **/
 const char **
-hb_shape_list_shapers (void)
+hb_shape_list_shapers ()
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-
-  if (unlikely (!shaper_list))
-  {
-    /* Not found; allocate one. */
-    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
-    if (unlikely (!shaper_list)) {
-      static const char *nil_shaper_list[] = {nullptr};
-      return nil_shaper_list;
-    }
-
-    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
-    unsigned int i;
-    for (i = 0; i < HB_SHAPERS_COUNT; i++)
-      shaper_list[i] = shapers[i].name;
-    shaper_list[i] = nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
-      free (shaper_list);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return shaper_list;
+  return static_shaper_list.get_unconst ();
 }
 
 
diff --git a/src/hb-shaper-impl-private.hh b/src/hb-shaper-impl-private.hh
deleted file mode 100644 (file)
index 7844081..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_IMPL_PRIVATE_HH
-#define HB_SHAPER_IMPL_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object)
-#endif
-
-
-#endif /* HB_SHAPER_IMPL_PRIVATE_HH */
diff --git a/src/hb-shaper-impl.hh b/src/hb-shaper-impl.hh
new file mode 100644 (file)
index 0000000..b674fce
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_IMPL_HH
+#define HB_SHAPER_IMPL_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-face.hh"
+#include "hb-font.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+
+#endif /* HB_SHAPER_IMPL_HH */
index b0835d3..36d8fc7 100644 (file)
 /* Only picks up fonts that have a "Silf" table. */
 HB_SHAPER_IMPLEMENT (graphite2)
 #endif
-#ifdef HAVE_CORETEXT
-/* Only picks up fonts that have a "mort" or "morx" table. */
-HB_SHAPER_IMPLEMENT (coretext_aat)
-#endif
 
-#ifdef HAVE_OT
 HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
-#endif
 
 #ifdef HAVE_UNISCRIBE
 HB_SHAPER_IMPLEMENT (uniscribe)
@@ -51,6 +45,10 @@ HB_SHAPER_IMPLEMENT (directwrite)
 #endif
 #ifdef HAVE_CORETEXT
 HB_SHAPER_IMPLEMENT (coretext)
+
+/* Only picks up fonts that have a "mort" or "morx" table.
+   Probably going to be removed https://github.com/harfbuzz/harfbuzz/issues/1478 */
+HB_SHAPER_IMPLEMENT (coretext_aat)
 #endif
 
 #ifdef HAVE_FALLBACK
diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh
deleted file mode 100644 (file)
index ce2d9f2..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright © 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.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_PRIVATE_HH
-#define HB_SHAPER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
-                                  hb_font_t          *font,
-                                  hb_buffer_t        *buffer,
-                                  const hb_feature_t *features,
-                                  unsigned int        num_features);
-
-#define HB_SHAPER_IMPLEMENT(name) \
-       extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-struct hb_shaper_pair_t {
-  char name[16];
-  hb_shape_func_t *func;
-};
-
-HB_INTERNAL const hb_shaper_pair_t *
-_hb_shapers_get (void);
-
-
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
-/* Means: succeeded, but don't need to keep any data. */
-#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-
-/* Means: tried but failed to create. */
-#define HB_SHAPER_DATA_INVALID ((void *) -1)
-#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
-
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)       hb_##shaper##_shaper_##object##_data_t
-#define HB_SHAPER_DATA_TYPE(shaper, object)            struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)      (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
-#define HB_SHAPER_DATA(shaper, object)                 HB_SHAPER_DATA_INSTANCE(shaper, object, object)
-#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_create
-#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)    _hb_##shaper##_shaper_##object##_data_destroy
-#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)     hb_##shaper##_shaper_##object##_data_ensure
-
-#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
-       HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
-       extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
-       HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
-       extern "C" HB_INTERNAL void \
-       HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
-       extern "C" HB_INTERNAL bool \
-       HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
-
-#define HB_SHAPER_DATA_DESTROY(shaper, object) \
-    if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
-      if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
-       HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
-bool \
-HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
-{\
-  retry: \
-  HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
-  if (likely (data) && !(condition)) { \
-    /* Drop and recreate. */ \
-    /* If someone dropped it in the mean time, throw it away and don't touch it. \
-     * Otherwise, destruct it. */ \
-    if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \
-      HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-    } \
-    goto retry; \
-  } \
-  if (unlikely (!data)) { \
-    data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
-    if (unlikely (!data)) \
-      data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
-    if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \
-      if (data && \
-         data != HB_SHAPER_DATA_INVALID && \
-         data != HB_SHAPER_DATA_SUCCEEDED) \
-       HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-      goto retry; \
-    } \
-  } \
-  return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
-}
-
-
-#endif /* HB_SHAPER_PRIVATE_HH */
index d44d8c9..575ab1f 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-atomic-private.hh"
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-machinery.hh"
 
 
-static const hb_shaper_pair_t all_shapers[] = {
+static const hb_shaper_entry_t all_shapers[] = {
 #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 };
 
-
-/* Thread-safe, lock-free, shapers */
-
-static const hb_shaper_pair_t *static_shapers;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shapers (void)
-{
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-  if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr))
-    goto retry;
-
-  if (unlikely (shapers != all_shapers))
-    free ((void *) shapers);
-}
+#if HB_USE_ATEXIT
+static void free_static_shapers ();
 #endif
 
-const hb_shaper_pair_t *
-_hb_shapers_get (void)
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+                                                         hb_shapers_lazy_loader_t>
 {
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-
-  if (unlikely (!shapers))
+  static hb_shaper_entry_t *create ()
   {
     char *env = getenv ("HB_SHAPER_LIST");
-    if (!env || !*env) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    if (!env || !*env)
+      return nullptr;
 
-    /* Not found; allocate one. */
-    shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
-    if (unlikely (!shapers)) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) calloc (1, sizeof (all_shapers));
+    if (unlikely (!shapers))
+      return nullptr;
 
     memcpy (shapers, all_shapers, sizeof (all_shapers));
 
      /* Reorder shaper list to prefer requested shapers. */
     unsigned int i = 0;
     char *end, *p = env;
-    for (;;) {
+    for (;;)
+    {
       end = strchr (p, ',');
       if (!end)
        end = p + strlen (p);
@@ -90,7 +68,7 @@ retry:
            0 == strncmp (shapers[j].name, p, end - p))
        {
          /* Reorder this shaper to position i */
-        struct hb_shaper_pair_t t = shapers[j];
+        struct hb_shaper_entry_t t = shapers[j];
         memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
         shapers[i] = t;
         i++;
@@ -102,15 +80,26 @@ retry:
        p = end + 1;
     }
 
-    if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) {
-      free (shapers);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shapers); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+    atexit (free_static_shapers);
 #endif
+
+    return shapers;
   }
+  static void destroy (const hb_shaper_entry_t *p) { free ((void *) p); }
+  static const hb_shaper_entry_t *get_null ()      { return all_shapers; }
+} static_shapers;
 
-  return shapers;
+#if HB_USE_ATEXIT
+static
+void free_static_shapers ()
+{
+  static_shapers.free_instance ();
+}
+#endif
+
+const hb_shaper_entry_t *
+_hb_shapers_get ()
+{
+  return static_shapers.get_unconst ();
 }
diff --git a/src/hb-shaper.hh b/src/hb-shaper.hh
new file mode 100644 (file)
index 0000000..79dc5d0
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_HH
+#define HB_SHAPER_HH
+
+#include "hb.hh"
+#include "hb-machinery.hh"
+
+typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
+                                  hb_font_t          *font,
+                                  hb_buffer_t        *buffer,
+                                  const hb_feature_t *features,
+                                  unsigned int        num_features);
+
+#define HB_SHAPER_IMPLEMENT(name) \
+       extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_shaper_entry_t {
+  char name[16];
+  hb_shape_func_t *func;
+};
+
+HB_INTERNAL const hb_shaper_entry_t *
+_hb_shapers_get ();
+
+
+template <typename Data, unsigned int WheresData, typename T>
+struct hb_shaper_lazy_loader_t;
+
+#define HB_SHAPER_ORDER(Shaper) \
+  HB_PASTE (HB_SHAPER_ORDER_, Shaper)
+enum hb_shaper_order_t
+{
+  _HB_SHAPER_ORDER_ORDER_ZERO,
+#define HB_SHAPER_IMPLEMENT(Shaper) \
+      HB_SHAPER_ORDER (Shaper),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  _HB_SHAPERS_COUNT_PLUS_ONE,
+  HB_SHAPERS_COUNT = _HB_SHAPERS_COUNT_PLUS_ONE - 1,
+};
+
+template <enum hb_shaper_order_t order, typename Object> struct hb_shaper_object_data_type_t;
+
+#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
+#define HB_SHAPER_DATA_TYPE(shaper, object)            hb_##shaper##_##object##_data_t
+#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_create
+#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)    _hb_##shaper##_shaper_##object##_data_destroy
+
+#define HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, object) \
+       \
+       struct HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
+       extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
+       HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object); \
+       extern "C" HB_INTERNAL void \
+       HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *shaper##_##object); \
+       \
+       template <> \
+       struct hb_shaper_object_data_type_t<HB_SHAPER_ORDER (shaper), hb_##object##_t> \
+       { \
+         typedef HB_SHAPER_DATA_TYPE(shaper, object) value; \
+       }; \
+       \
+       template <unsigned int WheresData> \
+       struct hb_shaper_lazy_loader_t<hb_##object##_t, WheresData, HB_SHAPER_DATA_TYPE(shaper, object)> \
+               : hb_lazy_loader_t<HB_SHAPER_DATA_TYPE(shaper, object), \
+                                  hb_shaper_lazy_loader_t<hb_##object##_t, \
+                                                          WheresData, \
+                                                          HB_SHAPER_DATA_TYPE(shaper, object)>, \
+                                  hb_##object##_t, WheresData> \
+       { \
+         typedef HB_SHAPER_DATA_TYPE(shaper, object) Type; \
+         static Type* create (hb_##object##_t *data) \
+         { return HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (data); } \
+         static Type *get_null () { return nullptr; } \
+         static void destroy (Type *p) { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (p); } \
+       }; \
+       \
+       static_assert (true, "") /* Require semicolon. */
+
+
+template <typename Object>
+struct hb_shaper_object_dataset_t
+{
+  void init0 (Object *parent_data)
+  {
+    this->parent_data = parent_data;
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.init0 ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+  void fini ()
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.fini ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+
+  Object *parent_data; /* MUST be JUST before the lazy loaders. */
+#define HB_SHAPER_IMPLEMENT(shaper) \
+       hb_shaper_lazy_loader_t<Object, HB_SHAPER_ORDER(shaper), \
+                               typename hb_shaper_object_data_type_t<HB_SHAPER_ORDER(shaper), Object>::value \
+                              > shaper;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+};
+
+#endif /* HB_SHAPER_HH */
index e26e5c8..4c51588 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+#include "hb-face.hh"
+
+#include "hb-aat-layout-common.hh"
+#include "hb-aat-layout-feat-table.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
 
 #ifndef HB_NO_VISIBILITY
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
+
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+
+DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
+/* Hand-coded because Lookup is a template.  Sad. */
+const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+
+
+unsigned int
+hb_face_t::load_num_glyphs () const
+{
+  hb_sanitize_context_t c = hb_sanitize_context_t ();
+  c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
+  hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
+  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+
+  unsigned int ret = maxp_table->get_num_glyphs ();
+  num_glyphs.set_relaxed (ret);
+  hb_blob_destroy (maxp_blob);
+  return ret;
+}
+
+unsigned int
+hb_face_t::load_upem () const
+{
+  unsigned int ret = table.head->get_upem ();
+  upem.set_relaxed (ret);
+  return ret;
+}
+
 #endif
index 679841c..c4cf666 100644 (file)
@@ -29,7 +29,7 @@
 #define HB_STRING_ARRAY_HH
 #endif
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 /* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf:
  * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */
diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc
new file mode 100644 (file)
index 0000000..3e617d5
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff-common.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-subset-cff-common.hh"
+
+/* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
+ * Rarely any/much smaller than format 3 anyway. */
+#define CFF_SERIALIZE_FDSELECT_0  0
+
+using namespace CFF;
+
+/**
+ * hb_plan_subset_cff_fdselect
+ * Determine an optimal FDSelect format according to a provided plan.
+ *
+ * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
+ * along with a font index remapping table
+ **/
+
+bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                           unsigned int fdCount,
+                           const FDSelect &src, /* IN */
+                           unsigned int &subset_fd_count /* OUT */,
+                           unsigned int &subset_fdselect_size /* OUT */,
+                           unsigned int &subset_fdselect_format /* OUT */,
+                           hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
+                           remap_t &fdmap /* OUT */)
+{
+  subset_fd_count = 0;
+  subset_fdselect_size = 0;
+  subset_fdselect_format = 0;
+  unsigned int  num_ranges = 0;
+
+  unsigned int subset_num_glyphs = glyphs.length;
+  if (subset_num_glyphs == 0)
+    return true;
+
+  {
+    /* use hb_set to determine the subset of font dicts */
+    hb_set_t  *set = hb_set_create ();
+    if (set == &Null (hb_set_t))
+      return false;
+    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
+    for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
+    {
+      hb_codepoint_t  fd = src.get_fd (glyphs[i]);
+      set->add (fd);
+
+      if (fd != prev_fd)
+      {
+       num_ranges++;
+       prev_fd = fd;
+       code_pair_t pair = { fd, i };
+       fdselect_ranges.push (pair);
+      }
+    }
+
+    subset_fd_count = set->get_population ();
+    if (subset_fd_count == fdCount)
+    {
+      /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
+      fdmap.identity (fdCount);
+      hb_set_destroy (set);
+    }
+    else
+    {
+      /* create a fdmap */
+      if (!fdmap.reset (fdCount))
+      {
+       hb_set_destroy (set);
+       return false;
+      }
+
+      hb_codepoint_t  fd = CFF_UNDEF_CODE;
+      while (set->next (&fd))
+       fdmap.add (fd);
+      hb_set_destroy (set);
+      if (unlikely (fdmap.get_count () != subset_fd_count))
+       return false;
+    }
+
+    /* update each font dict index stored as "code" in fdselect_ranges */
+    for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+      fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
+  }
+
+  /* determine which FDSelect format is most compact */
+  if (subset_fd_count > 0xFF)
+  {
+    if (unlikely (src.format != 4))
+      return false;
+    subset_fdselect_format = 4;
+    subset_fdselect_size = FDSelect::min_size + FDSelect4::min_size + FDSelect4_Range::static_size * num_ranges + HBUINT32::static_size;
+  }
+  else
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    unsigned int format0_size = FDSelect::min_size + FDSelect0::min_size + HBUINT8::static_size * subset_num_glyphs;
+#endif
+    unsigned int format3_size = FDSelect::min_size + FDSelect3::min_size + FDSelect3_Range::static_size * num_ranges + HBUINT16::static_size;
+
+#if CFF_SERIALIZE_FDSELECT_0
+    if (format0_size <= format3_size)
+    {
+      // subset_fdselect_format = 0;
+      subset_fdselect_size = format0_size;
+    }
+    else
+#endif
+    {
+      subset_fdselect_format = 3;
+      subset_fdselect_size = format3_size;
+    }
+  }
+
+  return true;
+}
+
+template <typename FDSELECT3_4>
+static inline bool
+serialize_fdselect_3_4 (hb_serialize_context_t *c,
+                         const unsigned int num_glyphs,
+                         const FDSelect &src,
+                         unsigned int size,
+                         const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->nRanges ().set (fdselect_ranges.length);
+  for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+  {
+    p->ranges[i].first.set (fdselect_ranges[i].glyph);
+    p->ranges[i].fd.set (fdselect_ranges[i].code);
+  }
+  p->sentinel().set (num_glyphs);
+  return_trace (true);
+}
+
+/**
+ * hb_serialize_cff_fdselect
+ * Serialize a subset FDSelect format planned above.
+ **/
+bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                         const unsigned int num_glyphs,
+                         const FDSelect &src,
+                         unsigned int fd_count,
+                         unsigned int fdselect_format,
+                         unsigned int size,
+                         const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSelect  *p = c->allocate_min<FDSelect> ();
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->format.set (fdselect_format);
+  size -= FDSelect::min_size;
+
+  switch (fdselect_format)
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    case 0:
+    {
+      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
+      if (unlikely (p == nullptr)) return_trace (false);
+      unsigned int range_index = 0;
+      unsigned int  fd = fdselect_ranges[range_index++].code;
+      for (unsigned int i = 0; i < num_glyphs; i++)
+      {
+       if ((range_index < fdselect_ranges.len) &&
+           (i >= fdselect_ranges[range_index].glyph))
+       {
+         fd = fdselect_ranges[range_index++].code;
+       }
+       p->fds[i].set (fd);
+      }
+      break;
+    }
+#endif /* CFF_SERIALIZE_FDSELECT_0 */
+
+    case 3:
+      return serialize_fdselect_3_4<FDSelect3> (c,
+                                               num_glyphs,
+                                               src,
+                                               size,
+                                               fdselect_ranges);
+
+    case 4:
+      return serialize_fdselect_3_4<FDSelect4> (c,
+                                               num_glyphs,
+                                               src,
+                                               size,
+                                               fdselect_ranges);
+
+    default:
+      assert(false);
+  }
+
+  return_trace (true);
+}
diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh
new file mode 100644 (file)
index 0000000..915b4c4
--- /dev/null
@@ -0,0 +1,990 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF_COMMON_HH
+#define HB_SUBSET_CFF_COMMON_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+/* Used for writing a temporary charstring */
+struct str_encoder_t
+{
+  str_encoder_t (str_buff_t &buff_)
+    : buff (buff_), error (false) {}
+
+  void reset () { buff.resize (0); }
+
+  void encode_byte (unsigned char b)
+  {
+    if (unlikely (buff.push (b) == &Crap(unsigned char)))
+      set_error ();
+  }
+
+  void encode_int (int v)
+  {
+    if ((-1131 <= v) && (v <= 1131))
+    {
+      if ((-107 <= v) && (v <= 107))
+       encode_byte (v + 139);
+      else if (v > 0)
+      {
+       v -= 108;
+       encode_byte ((v >> 8) + OpCode_TwoBytePosInt0);
+       encode_byte (v & 0xFF);
+      }
+      else
+      {
+       v = -v - 108;
+       encode_byte ((v >> 8) + OpCode_TwoByteNegInt0);
+       encode_byte (v & 0xFF);
+      }
+    }
+    else
+    {
+      if (unlikely (v < -32768))
+       v = -32768;
+      else if (unlikely (v > 32767))
+       v = 32767;
+      encode_byte (OpCode_shortint);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_num (const number_t& n)
+  {
+    if (n.in_int_range ())
+    {
+      encode_int (n.to_int ());
+    }
+    else
+    {
+      int32_t v = n.to_fixed ();
+      encode_byte (OpCode_fixedcs);
+      encode_byte ((v >> 24) & 0xFF);
+      encode_byte ((v >> 16) & 0xFF);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_op (op_code_t op)
+  {
+    if (Is_OpCode_ESC (op))
+    {
+      encode_byte (OpCode_escape);
+      encode_byte (Unmake_OpCode_ESC (op));
+    }
+    else
+      encode_byte (op);
+  }
+
+  void copy_str (const byte_str_t &str)
+  {
+    unsigned int  offset = buff.length;
+    buff.resize (offset + str.length);
+    if (unlikely (buff.length < offset + str.length))
+    {
+      set_error ();
+      return;
+    }
+    memcpy (&buff[offset], &str[0], str.length);
+  }
+
+  bool is_error () const { return error; }
+
+  protected:
+  void set_error () { error = true; }
+
+  str_buff_t &buff;
+  bool    error;
+};
+
+struct cff_sub_table_offsets_t {
+  cff_sub_table_offsets_t () : privateDictsOffset (0)
+  {
+    topDictInfo.init ();
+    FDSelectInfo.init ();
+    FDArrayInfo.init ();
+    charStringsInfo.init ();
+    globalSubrsInfo.init ();
+    localSubrsInfos.init ();
+  }
+
+  ~cff_sub_table_offsets_t () { localSubrsInfos.fini (); }
+
+  table_info_t     topDictInfo;
+  table_info_t     FDSelectInfo;
+  table_info_t     FDArrayInfo;
+  table_info_t     charStringsInfo;
+  unsigned int  privateDictsOffset;
+  table_info_t     globalSubrsInfo;
+  hb_vector_t<table_info_t>  localSubrsInfos;
+};
+
+template <typename OPSTR=op_str_t>
+struct cff_top_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                 const OPSTR &opstr,
+                 const cff_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+       return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.charStringsInfo.offset));
+
+      case OpCode_FDArray:
+       return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDArrayInfo.offset));
+
+      case OpCode_FDSelect:
+       return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDSelectInfo.offset));
+
+      default:
+       return_trace (copy_opstr (c, opstr));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const OPSTR &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+      case OpCode_FDSelect:
+       return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+       return opstr.str.length;
+    }
+  }
+};
+
+struct cff_font_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                 const op_str_t &opstr,
+                 const table_info_t &privateDictInfo) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_Private)
+    {
+      /* serialize the private dict size & offset as 2-byte & 4-byte integers */
+      if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
+                   !UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
+       return_trace (false);
+
+      /* serialize the opcode */
+      HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+      if (unlikely (p == nullptr)) return_trace (false);
+      p->set (OpCode_Private);
+
+      return_trace (true);
+    }
+    else
+    {
+      HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+      if (unlikely (d == nullptr)) return_trace (false);
+      memcpy (d, &opstr.str[0], opstr.str.length);
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_Private)
+      return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+    else
+      return opstr.str.length;
+  }
+};
+
+struct cff_private_dict_op_serializer_t : op_serializer_t
+{
+  cff_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
+    : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
+
+  bool serialize (hb_serialize_context_t *c,
+                 const op_str_t &opstr,
+                 const unsigned int subrsOffset) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return true;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || (subrsOffset == 0))
+       return_trace (true);
+      else
+       return_trace (FontDict::serialize_offset2_op (c, opstr.op, subrsOffset));
+    }
+    else
+      return_trace (copy_opstr (c, opstr));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr,
+                                         bool has_localsubr=true) const
+  {
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return 0;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || !has_localsubr)
+       return 0;
+      else
+       return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (opstr.op);
+    }
+    else
+      return opstr.str.length;
+  }
+
+  protected:
+  const bool  desubroutinize;
+  const bool  drop_hints;
+};
+
+struct flatten_param_t
+{
+  str_buff_t     &flatStr;
+  bool drop_hints;
+};
+
+template <typename ACC, typename ENV, typename OPSET>
+struct subr_flattener_t
+{
+  subr_flattener_t (const ACC &acc_,
+                   const hb_vector_t<hb_codepoint_t> &glyphs_,
+                   bool drop_hints_) : acc (acc_), glyphs (glyphs_),
+                                       drop_hints (drop_hints_) {}
+
+  bool flatten (str_buff_vec_t &flat_charstrings)
+  {
+    if (!flat_charstrings.resize (glyphs.length))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      flat_charstrings[i].init ();
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+       return false;
+      cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
+      interp.env.init (str, acc, fd);
+      flatten_param_t  param = { flat_charstrings[i], drop_hints };
+      if (unlikely (!interp.interpret (param)))
+       return false;
+    }
+    return true;
+  }
+
+  const ACC &acc;
+  const hb_vector_t<hb_codepoint_t> &glyphs;
+  bool  drop_hints;
+};
+
+struct subr_closures_t
+{
+  subr_closures_t () : valid (false), global_closure (nullptr)
+  { local_closures.init (); }
+
+  void init (unsigned int fd_count)
+  {
+    valid = true;
+    global_closure = hb_set_create ();
+    if (global_closure == hb_set_get_empty ())
+      valid = false;
+    if (!local_closures.resize (fd_count))
+      valid = false;
+
+    for (unsigned int i = 0; i < local_closures.length; i++)
+    {
+      local_closures[i] = hb_set_create ();
+      if (local_closures[i] == hb_set_get_empty ())
+       valid = false;
+    }
+  }
+
+  void fini ()
+  {
+    hb_set_destroy (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_destroy (local_closures[i]);
+    local_closures.fini ();
+  }
+
+  void reset ()
+  {
+    hb_set_clear (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_clear (local_closures[i]);
+  }
+
+  bool is_valid () const { return valid; }
+  bool  valid;
+  hb_set_t  *global_closure;
+  hb_vector_t<hb_set_t *> local_closures;
+};
+
+struct parsed_cs_op_t : op_str_t
+{
+  void init (unsigned int subr_num_ = 0)
+  {
+    op_str_t::init ();
+    subr_num = subr_num_;
+    drop_flag = false;
+    keep_flag = false;
+    skip_flag = false;
+  }
+
+  void fini () { op_str_t::fini (); }
+
+  bool for_drop () const { return drop_flag; }
+  void set_drop ()       { if (!for_keep ()) drop_flag = true; }
+
+  bool for_keep () const { return keep_flag; }
+  void set_keep ()       { keep_flag = true; }
+
+  bool for_skip () const { return skip_flag; }
+  void set_skip ()       { skip_flag = true; }
+
+  unsigned int  subr_num;
+
+  protected:
+  bool   drop_flag : 1;
+  bool   keep_flag : 1;
+  bool   skip_flag : 1;
+};
+
+struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
+{
+  void init ()
+  {
+    SUPER::init ();
+    parsed = false;
+    hint_dropped = false;
+    has_prefix_ = false;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref)
+  {
+    if (!is_parsed ())
+      SUPER::add_op (op, str_ref);
+  }
+
+  void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num)
+  {
+    if (!is_parsed ())
+    {
+      unsigned int parsed_len = get_count ();
+      if (likely (parsed_len > 0))
+       values[parsed_len-1].set_skip ();
+
+      parsed_cs_op_t val;
+      val.init (subr_num);
+      SUPER::add_op (op, str_ref, val);
+    }
+  }
+
+  void set_prefix (const number_t &num, op_code_t op = OpCode_Invalid)
+  {
+    has_prefix_ = true;
+    prefix_op_ = op;
+    prefix_num_ = num;
+  }
+
+  bool at_end (unsigned int pos) const
+  {
+    return ((pos + 1 >= values.length) /* CFF2 */
+       || (values[pos + 1].op == OpCode_return));
+  }
+
+  bool is_parsed () const { return parsed; }
+  void set_parsed ()      { parsed = true; }
+
+  bool is_hint_dropped () const { return hint_dropped; }
+  void set_hint_dropped ()      { hint_dropped = true; }
+
+  bool is_vsindex_dropped () const { return vsindex_dropped; }
+  void set_vsindex_dropped ()      { vsindex_dropped = true; }
+
+  bool has_prefix () const          { return has_prefix_; }
+  op_code_t prefix_op () const         { return prefix_op_; }
+  const number_t &prefix_num () const { return prefix_num_; }
+
+  protected:
+  bool    parsed;
+  bool    hint_dropped;
+  bool    vsindex_dropped;
+  bool    has_prefix_;
+  op_code_t    prefix_op_;
+  number_t     prefix_num_;
+
+  private:
+  typedef parsed_values_t<parsed_cs_op_t> SUPER;
+};
+
+struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
+{
+  void init (unsigned int len_ = 0)
+  {
+    SUPER::init ();
+    resize (len_);
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i].init ();
+  }
+  void fini () { SUPER::fini_deep (); }
+
+  private:
+  typedef hb_vector_t<parsed_cs_str_t> SUPER;
+};
+
+struct subr_subset_param_t
+{
+  void init (parsed_cs_str_t *parsed_charstring_,
+            parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
+            hb_set_t *global_closure_, hb_set_t *local_closure_,
+            bool drop_hints_)
+  {
+    parsed_charstring = parsed_charstring_;
+    current_parsed_str = parsed_charstring;
+    parsed_global_subrs = parsed_global_subrs_;
+    parsed_local_subrs = parsed_local_subrs_;
+    global_closure = global_closure_;
+    local_closure = local_closure_;
+    drop_hints = drop_hints_;
+  }
+
+  parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
+  {
+    switch (context.type)
+    {
+      case CSType_CharString:
+       return parsed_charstring;
+
+      case CSType_LocalSubr:
+       if (likely (context.subr_num < parsed_local_subrs->length))
+         return &(*parsed_local_subrs)[context.subr_num];
+       break;
+
+      case CSType_GlobalSubr:
+       if (likely (context.subr_num < parsed_global_subrs->length))
+         return &(*parsed_global_subrs)[context.subr_num];
+       break;
+    }
+    return nullptr;
+  }
+
+  template <typename ENV>
+  void set_current_str (ENV &env, bool calling)
+  {
+    parsed_cs_str_t  *parsed_str = get_parsed_str_for_context (env.context);
+    if (likely (parsed_str != nullptr))
+    {
+      /* If the called subroutine is parsed partially but not completely yet,
+       * it must be because we are calling it recursively.
+       * Handle it as an error. */
+      if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
+       env.set_error ();
+      else
+       current_parsed_str = parsed_str;
+    }
+    else
+      env.set_error ();
+  }
+
+  parsed_cs_str_t      *current_parsed_str;
+
+  parsed_cs_str_t      *parsed_charstring;
+  parsed_cs_str_vec_t  *parsed_global_subrs;
+  parsed_cs_str_vec_t  *parsed_local_subrs;
+  hb_set_t      *global_closure;
+  hb_set_t      *local_closure;
+  bool   drop_hints;
+};
+
+struct subr_remap_t : remap_t
+{
+  void create (hb_set_t *closure)
+  {
+    /* create a remapping of subroutine numbers from old to new.
+     * no optimization based on usage counts. fonttools doesn't appear doing that either.
+     */
+    reset (closure->get_max () + 1);
+    for (hb_codepoint_t old_num = 0; old_num < length; old_num++)
+    {
+      if (hb_set_has (closure, old_num))
+       add (old_num);
+    }
+
+    if (get_count () < 1240)
+      bias = 107;
+    else if (get_count () < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  hb_codepoint_t operator[] (unsigned int old_num) const
+  {
+    if (old_num >= length)
+      return CFF_UNDEF_CODE;
+    else
+      return remap_t::operator[] (old_num);
+  }
+
+  int biased_num (unsigned int old_num) const
+  {
+    hb_codepoint_t new_num = (*this)[old_num];
+    return (int)new_num - bias;
+  }
+
+  protected:
+  int bias;
+};
+
+struct subr_remap_ts
+{
+  subr_remap_ts ()
+  {
+    global_remap.init ();
+    local_remaps.init ();
+  }
+
+  ~subr_remap_ts () { fini (); }
+
+  void init (unsigned int fdCount)
+  {
+    local_remaps.resize (fdCount);
+    for (unsigned int i = 0; i < fdCount; i++)
+      local_remaps[i].init ();
+  }
+
+  void create (subr_closures_t& closures)
+  {
+    global_remap.create (closures.global_closure);
+    for (unsigned int i = 0; i < local_remaps.length; i++)
+      local_remaps[i].create (closures.local_closures[i]);
+  }
+
+  void fini ()
+  {
+    global_remap.fini ();
+    local_remaps.fini_deep ();
+  }
+
+  subr_remap_t        global_remap;
+  hb_vector_t<subr_remap_t>  local_remaps;
+};
+
+template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET>
+struct subr_subsetter_t
+{
+  subr_subsetter_t ()
+  {
+    parsed_charstrings.init ();
+    parsed_global_subrs.init ();
+    parsed_local_subrs.init ();
+  }
+
+  ~subr_subsetter_t ()
+  {
+    closures.fini ();
+    remaps.fini ();
+    parsed_charstrings.fini_deep ();
+    parsed_global_subrs.fini_deep ();
+    parsed_local_subrs.fini_deep ();
+  }
+
+  /* Subroutine subsetting with --no-desubroutinize runs in phases:
+   *
+   * 1. execute charstrings/subroutines to determine subroutine closures
+   * 2. parse out all operators and numbers
+   * 3. mark hint operators and operands for removal if --no-hinting
+   * 4. re-encode all charstrings and subroutines with new subroutine numbers
+   *
+   * Phases #1 and #2 are done at the same time in collect_subrs ().
+   * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required),
+   * because we can't tell if a number belongs to a hint op until we see the first moveto.
+   *
+   * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number
+   * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine.
+   */
+  bool subset (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, bool drop_hints)
+  {
+    closures.init (acc.fdCount);
+    remaps.init (acc.fdCount);
+
+    parsed_charstrings.init (glyphs.length);
+    parsed_global_subrs.init (acc.globalSubrs->count);
+    parsed_local_subrs.resize (acc.fdCount);
+    for (unsigned int i = 0; i < acc.fdCount; i++)
+    {
+      parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
+    }
+    if (unlikely (!closures.valid))
+      return false;
+
+    /* phase 1 & 2 */
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+       return false;
+
+      cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
+      interp.env.init (str, acc, fd);
+
+      subr_subset_param_t  param;
+      param.init (&parsed_charstrings[i],
+                 &parsed_global_subrs,  &parsed_local_subrs[fd],
+                 closures.global_closure, closures.local_closures[fd],
+                 drop_hints);
+
+      if (unlikely (!interp.interpret (param)))
+       return false;
+
+      /* finalize parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
+      SUBSETTER::finalize_parsed_str (interp.env, param, parsed_charstrings[i]);
+    }
+
+    if (drop_hints)
+    {
+      /* mark hint ops and arguments for drop */
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+       unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+       if (unlikely (fd >= acc.fdCount))
+         return false;
+       subr_subset_param_t  param;
+       param.init (&parsed_charstrings[i],
+                   &parsed_global_subrs,  &parsed_local_subrs[fd],
+                   closures.global_closure, closures.local_closures[fd],
+                   drop_hints);
+
+       drop_hints_param_t  drop;
+       if (drop_hints_in_str (parsed_charstrings[i], param, drop))
+       {
+         parsed_charstrings[i].set_hint_dropped ();
+         if (drop.vsindex_dropped)
+           parsed_charstrings[i].set_vsindex_dropped ();
+       }
+      }
+
+      /* after dropping hints recreate closures of actually used subrs */
+      closures.reset ();
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+       unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+       if (unlikely (fd >= acc.fdCount))
+         return false;
+       subr_subset_param_t  param;
+       param.init (&parsed_charstrings[i],
+                   &parsed_global_subrs,  &parsed_local_subrs[fd],
+                   closures.global_closure, closures.local_closures[fd],
+                   drop_hints);
+       collect_subr_refs_in_str (parsed_charstrings[i], param);
+      }
+    }
+
+    remaps.create (closures);
+
+    return true;
+  }
+
+  bool encode_charstrings (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, str_buff_vec_t &buffArray) const
+  {
+    if (unlikely (!buffArray.resize (glyphs.length)))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int  fd = acc.fdSelect->get_fd (glyphs[i]);
+      if (unlikely (fd >= acc.fdCount))
+       return false;
+      if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+       return false;
+    }
+    return true;
+  }
+
+  bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    unsigned int  count = remap.get_count ();
+
+    if (unlikely (!buffArray.resize (count)))
+      return false;
+    for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
+    {
+      hb_codepoint_t new_num = remap[old_num];
+      if (new_num != CFF_UNDEF_CODE)
+      {
+       if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+         return false;
+      }
+    }
+    return true;
+  }
+
+  bool encode_globalsubrs (str_buff_vec_t &buffArray)
+  {
+    return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+  }
+
+  bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+  }
+
+  protected:
+  struct drop_hints_param_t
+  {
+    drop_hints_param_t ()
+      : seen_moveto (false),
+       ends_in_hint (false),
+       vsindex_dropped (false) {}
+
+    bool  seen_moveto;
+    bool  ends_in_hint;
+    bool  vsindex_dropped;
+  };
+
+  bool drop_hints_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                          parsed_cs_str_vec_t &subrs, unsigned int subr_num,
+                          const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    drop.ends_in_hint = false;
+    bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop);
+
+    /* if this subr ends with a stem hint (i.e., not a number a potential argument for moveto),
+     * then this entire subroutine must be a hint. drop its call. */
+    if (drop.ends_in_hint)
+    {
+      str.values[pos].set_drop ();
+      /* if this subr call is at the end of the parent subr, propagate the flag
+       * otherwise reset the flag */
+      if (!str.at_end (pos))
+       drop.ends_in_hint = false;
+    }
+
+    return has_hint;
+  }
+
+  /* returns true if it sees a hint op before the first moveto */
+  bool drop_hints_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    bool  seen_hint = false;
+
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      bool  has_hint = false;
+      switch (str.values[pos].op)
+      {
+       case OpCode_callsubr:
+         has_hint = drop_hints_in_subr (str, pos,
+                                       *param.parsed_local_subrs, str.values[pos].subr_num,
+                                       param, drop);
+
+         break;
+
+       case OpCode_callgsubr:
+         has_hint = drop_hints_in_subr (str, pos,
+                                       *param.parsed_global_subrs, str.values[pos].subr_num,
+                                       param, drop);
+         break;
+
+       case OpCode_rmoveto:
+       case OpCode_hmoveto:
+       case OpCode_vmoveto:
+         drop.seen_moveto = true;
+         break;
+
+       case OpCode_hintmask:
+       case OpCode_cntrmask:
+         if (drop.seen_moveto)
+         {
+           str.values[pos].set_drop ();
+           break;
+         }
+         HB_FALLTHROUGH;
+
+       case OpCode_hstemhm:
+       case OpCode_vstemhm:
+       case OpCode_hstem:
+       case OpCode_vstem:
+         has_hint = true;
+         str.values[pos].set_drop ();
+         if (str.at_end (pos))
+           drop.ends_in_hint = true;
+         break;
+
+       case OpCode_dotsection:
+         str.values[pos].set_drop ();
+         break;
+
+       default:
+         /* NONE */
+         break;
+      }
+      if (has_hint)
+      {
+       for (int i = pos - 1; i >= 0; i--)
+       {
+         parsed_cs_op_t  &csop = str.values[(unsigned)i];
+         if (csop.for_drop ())
+           break;
+         csop.set_drop ();
+         if (csop.op == OpCode_vsindexcs)
+           drop.vsindex_dropped = true;
+       }
+       seen_hint |= has_hint;
+      }
+    }
+
+    return seen_hint;
+  }
+
+  void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                                 unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+                                 hb_set_t *closure,
+                                 const subr_subset_param_t &param)
+  {
+    hb_set_add (closure, subr_num);
+    collect_subr_refs_in_str (subrs[subr_num], param);
+  }
+
+  void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+  {
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      if (!str.values[pos].for_drop ())
+      {
+       switch (str.values[pos].op)
+       {
+         case OpCode_callsubr:
+           collect_subr_refs_in_subr (str, pos,
+                                      str.values[pos].subr_num, *param.parsed_local_subrs,
+                                      param.local_closure, param);
+           break;
+
+         case OpCode_callgsubr:
+           collect_subr_refs_in_subr (str, pos,
+                                      str.values[pos].subr_num, *param.parsed_global_subrs,
+                                      param.global_closure, param);
+           break;
+
+         default: break;
+       }
+      }
+    }
+  }
+
+  bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
+  {
+    buff.init ();
+    str_encoder_t  encoder (buff);
+    encoder.reset ();
+    /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
+     * re-insert it at the beginning of charstreing */
+    if (str.has_prefix () && str.is_hint_dropped ())
+    {
+      encoder.encode_num (str.prefix_num ());
+      if (str.prefix_op () != OpCode_Invalid)
+       encoder.encode_op (str.prefix_op ());
+    }
+    for (unsigned int i = 0; i < str.get_count(); i++)
+    {
+      const parsed_cs_op_t  &opstr = str.values[i];
+      if (!opstr.for_drop () && !opstr.for_skip ())
+      {
+       switch (opstr.op)
+       {
+         case OpCode_callsubr:
+           encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
+           encoder.encode_op (OpCode_callsubr);
+           break;
+
+         case OpCode_callgsubr:
+           encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
+           encoder.encode_op (OpCode_callgsubr);
+           break;
+
+         default:
+           encoder.copy_str (opstr.str);
+           break;
+       }
+      }
+    }
+    return !encoder.is_error ();
+  }
+
+  protected:
+  subr_closures_t            closures;
+
+  parsed_cs_str_vec_t         parsed_charstrings;
+  parsed_cs_str_vec_t         parsed_global_subrs;
+  hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
+
+  subr_remap_ts                remaps;
+
+  private:
+  typedef typename SUBRS::count_type subr_count_type;
+};
+
+} /* namespace CFF */
+
+HB_INTERNAL bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                           unsigned int fdCount,
+                           const CFF::FDSelect &src, /* IN */
+                           unsigned int &subset_fd_count /* OUT */,
+                           unsigned int &subset_fdselect_size /* OUT */,
+                           unsigned int &subset_fdselect_format /* OUT */,
+                           hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
+                           CFF::remap_t &fdmap /* OUT */);
+
+HB_INTERNAL bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                         unsigned int num_glyphs,
+                         const CFF::FDSelect &src,
+                         unsigned int fd_count,
+                         unsigned int fdselect_format,
+                         unsigned int size,
+                         const hb_vector_t<CFF::code_pair_t> &fdselect_ranges);
+
+#endif /* HB_SUBSET_CFF_COMMON_HH */
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
new file mode 100644 (file)
index 0000000..5133a4d
--- /dev/null
@@ -0,0 +1,1103 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff1.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+struct remap_sid_t : remap_t
+{
+  unsigned int add (unsigned int sid)
+  {
+    if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
+      return offset_sid (remap_t::add (unoffset_sid (sid)));
+    else
+      return sid;
+  }
+
+  unsigned int operator[] (unsigned int sid) const
+  {
+    if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+      return sid;
+    else
+      return offset_sid (remap_t::operator [] (unoffset_sid (sid)));
+  }
+
+  static const unsigned int num_std_strings = 391;
+
+  static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+  static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
+  static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+};
+
+struct cff1_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff1_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      nameIndexOffset (0),
+      encodingOffset (0)
+  {
+    stringIndexInfo.init ();
+    charsetInfo.init ();
+    privateDictInfo.init ();
+  }
+
+  unsigned int  nameIndexOffset;
+  table_info_t stringIndexInfo;
+  unsigned int  encodingOffset;
+  table_info_t charsetInfo;
+  table_info_t privateDictInfo;
+};
+
+/* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
+struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
+{
+  void init (const cff1_top_dict_values_t *base_= &Null(cff1_top_dict_values_t))
+  {
+    SUPER::init ();
+    base = base_;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  unsigned get_count () const { return base->get_count () + SUPER::get_count (); }
+  const cff1_top_dict_val_t &get_value (unsigned int i) const
+  {
+    if (i < base->get_count ())
+      return (*base)[i];
+    else
+      return SUPER::values[i - base->get_count ()];
+  }
+  const cff1_top_dict_val_t &operator [] (unsigned int i) const { return get_value (i); }
+
+  void reassignSIDs (const remap_sid_t& sidmap)
+  {
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      nameSIDs[i] = sidmap[base->nameSIDs[i]];
+  }
+
+  protected:
+  typedef cff1_top_dict_values_t SUPER;
+  const cff1_top_dict_values_t *base;
+};
+
+struct top_dict_modifiers_t
+{
+  top_dict_modifiers_t (const cff1_sub_table_offsets_t &offsets_,
+                          const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
+    : offsets (offsets_),
+      nameSIDs (nameSIDs_)
+  {}
+
+  const cff1_sub_table_offsets_t &offsets;
+  const unsigned int   (&nameSIDs)[name_dict_values_t::ValCount];
+};
+
+struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dict_val_t>
+{
+  bool serialize (hb_serialize_context_t *c,
+                 const cff1_top_dict_val_t &opstr,
+                 const top_dict_modifiers_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+       return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
+
+      case OpCode_Encoding:
+       return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
+
+      case OpCode_Private:
+       {
+         if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
+           return_trace (false);
+         if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
+           return_trace (false);
+         HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+         if (unlikely (p == nullptr)) return_trace (false);
+         p->set (OpCode_Private);
+       }
+       break;
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+       return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
+
+      case OpCode_ROS:
+       {
+         /* for registry & ordering, reassigned SIDs are serialized
+          * for supplement, the original byte string is copied along with the op code */
+         op_str_t supp_op;
+         supp_op.op = op;
+         if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+           return_trace (false);
+         supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+         return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
+                       UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
+                       copy_opstr (c, supp_op));
+       }
+      default:
+       return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.offsets));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const cff1_top_dict_val_t &opstr) const
+  {
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+      case OpCode_Encoding:
+       return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+
+      case OpCode_Private:
+       return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+       return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
+
+      case OpCode_ROS:
+       return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.length - opstr.last_arg_offset)/* supplement + op */;
+
+      default:
+       return cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct font_dict_values_mod_t
+{
+  void init (const cff1_font_dict_values_t *base_,
+            unsigned int fontName_,
+            const table_info_t &privateDictInfo_)
+  {
+    base = base_;
+    fontName = fontName_;
+    privateDictInfo = privateDictInfo_;
+  }
+
+  unsigned get_count () const { return base->get_count (); }
+
+  const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
+
+  const cff1_font_dict_values_t    *base;
+  table_info_t            privateDictInfo;
+  unsigned int         fontName;
+};
+
+struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                 const op_str_t &opstr,
+                 const font_dict_values_mod_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_FontName)
+      return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
+    else
+      return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_FontName)
+      return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
+    else
+      return SUPER::calculate_serialized_size (opstr);
+  }
+
+  private:
+  typedef cff_font_dict_op_serializer_t SUPER;
+};
+
+struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    if (env.arg_start > 0)
+      flush_width (env, param);
+
+    switch (op)
+    {
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+      case OpCode_dotsection:
+       if (param.drop_hints)
+       {
+         env.clear_args ();
+         return;
+       }
+       HB_FALLTHROUGH;
+
+      default:
+       SUPER::flush_args_and_op (op, env, param);
+       break;
+    }
+  }
+  static void flush_args (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
+      encoder.encode_num (env.eval_arg (i));
+    SUPER::flush_args (env, param);
+  }
+
+  static void flush_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_op (op);
+  }
+
+  static void flush_width (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    assert (env.has_width);
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_num (env.width);
+  }
+
+  static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    SUPER::flush_hintmask (op, env, param);
+    if (!param.drop_hints)
+    {
+      str_encoder_t  encoder (param.flatStr);
+      for (unsigned int i = 0; i < env.hintmask_size; i++)
+       encoder.encode_byte (env.str_ref[i]);
+    }
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t> SUPER;
+};
+
+struct range_list_t : hb_vector_t<code_pair_t>
+{
+  /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
+  bool finalize (unsigned int last_glyph)
+  {
+    bool  two_byte = false;
+    for (unsigned int i = (*this).length; i > 0; i--)
+    {
+      code_pair_t &pair = (*this)[i - 1];
+      unsigned int  nLeft = last_glyph - pair.glyph - 1;
+      if (nLeft >= 0x100)
+       two_byte = true;
+      last_glyph = pair.glyph;
+      pair.glyph = nLeft;
+    }
+    return two_byte;
+  }
+};
+
+struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+       param.current_parsed_str->add_op (op, env.str_ref);
+       param.current_parsed_str->set_parsed ();
+       env.returnFromSubr ();
+       param.set_current_str (env, false);
+       break;
+
+      case OpCode_endchar:
+       param.current_parsed_str->add_op (op, env.str_ref);
+       param.current_parsed_str->set_parsed ();
+       SUPER::process_op (op, env, param);
+       break;
+
+      case OpCode_callsubr:
+       process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+       break;
+
+      case OpCode_callgsubr:
+       process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+       break;
+
+      default:
+       SUPER::process_op (op, env, param);
+       param.current_parsed_str->add_op (op, env.str_ref);
+       break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                cff1_cs_interp_env_t &env, subr_subset_param_t& param,
+                                cff1_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* insert width at the beginning of the charstring as necessary */
+    if (env.has_width)
+      charstring.set_prefix (env.width);
+
+    /* subroutines/charstring left on the call stack are legally left unmarked
+     * unmarked when a subroutine terminates with endchar. mark them.
+     */
+    param.current_parsed_str->set_parsed ();
+    for (unsigned int i = 0; i < env.callStack.get_count (); i++)
+    {
+      parsed_cs_str_t  *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
+      if (likely (parsed_str != nullptr))
+       parsed_str->set_parsed ();
+      else
+       env.set_error ();
+    }
+  }
+};
+
+struct cff_subset_plan {
+  cff_subset_plan ()
+    : final_size (0),
+      offsets (),
+      orig_fdcount (0),
+      subset_fdcount (1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize(false)
+  {
+    topdict_sizes.init ();
+    topdict_sizes.resize (1);
+    topdict_mod.init ();
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    fontdicts_mod.init ();
+    subset_enc_code_ranges.init ();
+    subset_enc_supp_codes.init ();
+    subset_charset_ranges.init ();
+    sidmap.init ();
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      topDictModSIDs[i] = CFF_UNDEF_SID;
+  }
+
+  ~cff_subset_plan ()
+  {
+    topdict_sizes.fini ();
+    topdict_mod.fini ();
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    fontdicts_mod.fini ();
+    subset_enc_code_ranges.fini ();
+    subset_enc_supp_codes.fini ();
+    subset_charset_ranges.fini ();
+    sidmap.fini ();
+  }
+
+  unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    const Encoding *encoding = acc.encoding;
+    unsigned int  size0, size1, supp_size;
+    hb_codepoint_t  code, last_code = CFF_UNDEF_CODE;
+    hb_vector_t<hb_codepoint_t> supp_codes;
+
+    subset_enc_code_ranges.resize (0);
+    supp_size = 0;
+    supp_codes.init ();
+
+    subset_enc_num_codes = plan->glyphs.length - 1;
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      code = acc.glyph_to_code (orig_glyph);
+      if (code == CFF_UNDEF_CODE)
+      {
+       subset_enc_num_codes = glyph - 1;
+       break;
+      }
+
+      if (code != last_code + 1)
+      {
+       code_pair_t pair = { code, glyph };
+       subset_enc_code_ranges.push (pair);
+      }
+      last_code = code;
+
+      if (encoding != &Null(Encoding))
+      {
+       hb_codepoint_t  sid = acc.glyph_to_sid (orig_glyph);
+       encoding->get_supplement_codes (sid, supp_codes);
+       for (unsigned int i = 0; i < supp_codes.length; i++)
+       {
+         code_pair_t pair = { supp_codes[i], sid };
+         subset_enc_supp_codes.push (pair);
+       }
+       supp_size += SuppEncoding::static_size * supp_codes.length;
+      }
+    }
+    supp_codes.fini ();
+
+    subset_enc_code_ranges.finalize (glyph);
+
+    assert (subset_enc_num_codes <= 0xFF);
+    size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
+    size1 = Encoding1::min_size + Encoding1_Range::static_size * subset_enc_code_ranges.length;
+
+    if (size0 < size1)
+      subset_enc_format = 0;
+    else
+      subset_enc_format = 1;
+
+    return Encoding::calculate_serialized_size (
+                       subset_enc_format,
+                       subset_enc_format? subset_enc_code_ranges.length: subset_enc_num_codes,
+                       subset_enc_supp_codes.length);
+  }
+
+  unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    unsigned int  size0, size_ranges;
+    hb_codepoint_t  sid, last_sid = CFF_UNDEF_CODE;
+
+    subset_charset_ranges.resize (0);
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      sid = acc.glyph_to_sid (orig_glyph);
+
+      if (!acc.is_CID ())
+       sid = sidmap.add (sid);
+
+      if (sid != last_sid + 1)
+      {
+       code_pair_t pair = { sid, glyph };
+       subset_charset_ranges.push (pair);
+      }
+      last_sid = sid;
+    }
+
+    bool two_byte = subset_charset_ranges.finalize (glyph);
+
+    size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs.length - 1);
+    if (!two_byte)
+      size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+    else
+      size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+
+    if (size0 < size_ranges)
+      subset_charset_format = 0;
+    else if (!two_byte)
+      subset_charset_format = 1;
+    else
+      subset_charset_format = 2;
+
+    return Charset::calculate_serialized_size (
+                       subset_charset_format,
+                       subset_charset_format? subset_charset_ranges.length: plan->glyphs.length);
+  }
+
+  bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
+  {
+    if (unlikely (!sidmap.reset (acc.stringIndex->count)))
+      return false;
+
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+    {
+      unsigned int sid = acc.topDict.nameSIDs[i];
+      if (sid != CFF_UNDEF_SID)
+      {
+       (void)sidmap.add (sid);
+       topDictModSIDs[i] = sidmap[sid];
+      }
+    }
+
+    if (acc.fdArray != &Null(CFF1FDArray))
+      for (unsigned int i = 0; i < orig_fdcount; i++)
+       if (fdmap.includes (i))
+         (void)sidmap.add (acc.fontDicts[i].fontName);
+
+    return true;
+  }
+
+  bool create (const OT::cff1::accelerator_subset_t &acc,
+                     hb_subset_plan_t *plan)
+  {
+     /* make sure notdef is first */
+    if ((plan->glyphs.length == 0) || (plan->glyphs[0] != 0)) return false;
+
+    final_size = 0;
+    num_glyphs = plan->glyphs.length;
+    orig_fdcount = acc.fdCount;
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* check whether the subset renumbers any glyph IDs */
+    gid_renum = false;
+    for (unsigned int glyph = 0; glyph < plan->glyphs.length; glyph++)
+    {
+      if (plan->glyphs[glyph] != glyph) {
+       gid_renum = true;
+       break;
+      }
+    }
+
+    subset_charset = gid_renum || !acc.is_predef_charset ();
+    subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
+
+    /* CFF header */
+    final_size += OT::cff1::static_size;
+
+    /* Name INDEX */
+    offsets.nameIndexOffset = final_size;
+    final_size += acc.nameIndex->get_size ();
+
+    /* top dict INDEX */
+    {
+      /* Add encoding/charset to a (copy of) top dict as necessary */
+      topdict_mod.init (&acc.topDict);
+      bool need_to_add_enc = (subset_encoding && !acc.topDict.has_op (OpCode_Encoding));
+      bool need_to_add_set = (subset_charset && !acc.topDict.has_op (OpCode_charset));
+      if (need_to_add_enc || need_to_add_set)
+      {
+       if (need_to_add_enc)
+         topdict_mod.add_op (OpCode_Encoding);
+       if (need_to_add_set)
+         topdict_mod.add_op (OpCode_charset);
+      }
+      offsets.topDictInfo.offset = final_size;
+      cff1_top_dict_op_serializer_t topSzr;
+      unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
+      offsets.topDictInfo.offSize = calcOffSize(topDictSize);
+      if (unlikely (offsets.topDictInfo.offSize > 4))
+       return false;
+      final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<cff1_top_dict_values_mod_t>
+                                               (offsets.topDictInfo.offSize,
+                                                &topdict_mod, 1, topdict_sizes, topSzr);
+    }
+
+    /* Determine re-mapping of font index as fdmap among other info */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+       if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                 orig_fdcount,
+                                 *acc.fdSelect,
+                                 subset_fdcount,
+                                 offsets.FDSelectInfo.size,
+                                 subset_fdselect_format,
+                                 subset_fdselect_ranges,
+                                 fdmap)))
+       return false;
+    }
+    else
+      fdmap.identity (1);
+
+    /* remove unused SIDs & reassign SIDs */
+    {
+      /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
+      if (unlikely (!collect_sids_in_dicts (acc)))
+       return false;
+      if (unlikely (sidmap.get_count () > 0x8000))     /* assumption: a dict won't reference that many strings */
+       return false;
+      if (subset_charset)
+       offsets.charsetInfo.size = plan_subset_charset (acc, plan);
+
+      topdict_mod.reassignSIDs (sidmap);
+    }
+
+    /* String INDEX */
+    {
+      offsets.stringIndexInfo.offset = final_size;
+      offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
+      final_size += offsets.stringIndexInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t>
+                   flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+       return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+       return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+       return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+       return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.globalSubrsInfo.offSize > 4))
+       return false;
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+       return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+       return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+       subset_localsubrs[fd].init ();
+       offsets.localSubrsInfos[fd].init ();
+       if (fdmap.includes (fd))
+       {
+         if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+           return false;
+
+         unsigned int dataSize = subset_localsubrs[fd].total_size ();
+         if (dataSize > 0)
+         {
+           offsets.localSubrsInfos[fd].offset = final_size;
+           offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+           if (unlikely (offsets.localSubrsInfos[fd].offSize > 4))
+             return false;
+           offsets.localSubrsInfos[fd].size = CFF1Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+         }
+       }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* Encoding */
+    if (!subset_encoding)
+      offsets.encodingOffset = acc.topDict.EncodingOffset;
+    else
+    {
+      offsets.encodingOffset = final_size;
+      final_size += plan_subset_encoding (acc, plan);
+    }
+
+    /* Charset */
+    if (!subset_charset && acc.is_predef_charset ())
+      offsets.charsetInfo.offset = acc.topDict.CharsetOffset;
+    else
+      offsets.charsetInfo.offset = final_size;
+    final_size += offsets.charsetInfo.size;
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      final_size += offsets.FDSelectInfo.size;
+    }
+
+    /* FDArray (FDIndex) */
+    if (acc.fdArray != &Null(CFF1FDArray)) {
+      offsets.FDArrayInfo.offset = final_size;
+      cff1_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+       if (fdmap.includes (i))
+         dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      if (unlikely (offsets.FDArrayInfo.offSize > 4))
+       return false;
+      final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.charStringsInfo.offSize > 4))
+       return false;
+      final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictInfo.offset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+       bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+       cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
+       unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+       table_info_t  privInfo = { final_size, priv_size, 0 };
+       font_dict_values_mod_t fontdict_mod;
+       if (!acc.is_CID ())
+         fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
+       else
+         fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
+       fontdicts_mod.push (fontdict_mod);
+       final_size += privInfo.size;
+
+       if (!plan->desubroutinize && has_localsubrs)
+       {
+         offsets.localSubrsInfos[i].offset = final_size;
+         final_size += offsets.localSubrsInfos[i].size;
+       }
+      }
+    }
+
+    if (!acc.is_CID ())
+      offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
+
+    return ((subset_charstrings.length == plan->glyphs.length)
+          && (fontdicts_mod.length == subset_fdcount));
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int       final_size;
+  hb_vector_t<unsigned int>    topdict_sizes;
+  cff1_top_dict_values_mod_t   topdict_mod;
+  cff1_sub_table_offsets_t     offsets;
+
+  unsigned int    num_glyphs;
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  /* font dict index remap table from fullset FDArray to subset FDArray.
+   * set to CFF_UNDEF_CODE if excluded from subset */
+  remap_t   fdmap;
+
+  str_buff_vec_t               subset_charstrings;
+  str_buff_vec_t               subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t>  subset_localsubrs;
+  hb_vector_t<font_dict_values_mod_t>  fontdicts_mod;
+
+  bool         drop_hints;
+
+  bool         gid_renum;
+  bool         subset_encoding;
+  uint8_t      subset_enc_format;
+  unsigned int subset_enc_num_codes;
+  range_list_t subset_enc_code_ranges;
+  hb_vector_t<code_pair_t>  subset_enc_supp_codes;
+
+  uint8_t      subset_charset_format;
+  range_list_t subset_charset_ranges;
+  bool         subset_charset;
+
+  remap_sid_t  sidmap;
+  unsigned int topDictModSIDs[name_dict_values_t::ValCount];
+
+  bool         desubroutinize;
+  cff1_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff1 (const cff_subset_plan &plan,
+                               const OT::cff1::accelerator_subset_t  &acc,
+                               const hb_vector_t<hb_codepoint_t>& glyphs,
+                               unsigned int dest_sz,
+                               void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff1 *cff = c.start_serialize<OT::cff1> ();
+  if (unlikely (!c.extend_min (*cff)))
+    return false;
+
+  /* header */
+  cff->version.major.set (0x01);
+  cff->version.minor.set (0x00);
+  cff->nameIndex.set (cff->min_size);
+  cff->offSize.set (4); /* unused? */
+
+  /* name INDEX */
+  {
+    assert (cff->nameIndex == (unsigned) (c.head - c.start));
+    CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
+      return false;
+    }
+  }
+
+  /* top dict INDEX */
+  {
+    assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
+    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
+    if (dest == nullptr) return false;
+    cff1_top_dict_op_serializer_t topSzr;
+    top_dict_modifiers_t  modifier (plan.offsets, plan.topDictModSIDs);
+    if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
+                                   &plan.topdict_mod, 1,
+                                   plan.topdict_sizes, topSzr, modifier)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
+      return false;
+    }
+  }
+
+  /* String INDEX */
+  {
+    assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start));
+    CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (plan.offsets.globalSubrsInfo.offset != 0);
+    assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start));
+
+    CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* Encoding */
+  if (plan.subset_encoding)
+  {
+    assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start));
+    Encoding *dest = c.start_embed<Encoding> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                   plan.subset_enc_format,
+                                   plan.subset_enc_num_codes,
+                                   plan.subset_enc_code_ranges,
+                                   plan.subset_enc_supp_codes)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
+      return false;
+    }
+  }
+
+  /* Charset */
+  if (plan.subset_charset)
+  {
+    assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start));
+    Charset *dest = c.start_embed<Charset> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                   plan.subset_charset_format,
+                                   plan.num_glyphs,
+                                   plan.subset_charset_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF1FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *acc.fdSelect, acc.fdCount,
+                                             plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                             plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  if (acc.fdArray != &Null(CFF1FDArray))
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF1FDArray  *fda = c.start_embed<CFF1FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff1_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                  plan.fontdicts_mod,
+                                  fontSzr)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF1CharStrings  *cs = c.start_embed<CFF1CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+       DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+       return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+       CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+       if (unlikely (dest == nullptr)) return false;
+       if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+       {
+         DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+         return false;
+       }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
+               const char              *data,
+               hb_subset_plan_t        *plan,
+               hb_blob_t               **prime /* OUT */)
+{
+  cff_subset_plan cff_plan;
+
+  if (unlikely (!cff_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff_prime_size = cff_plan.get_final_size ();
+  char *cff_prime_data = (char *) calloc (1, cff_prime_size);
+
+  if (unlikely (!_write_cff1 (cff_plan, acc, plan->glyphs,
+                             cff_prime_size, cff_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
+    free (cff_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff_prime_data,
+                          cff_prime_size,
+                          HB_MEMORY_MODE_READONLY,
+                          cff_prime_data,
+                          free);
+  return true;
+}
+
+/**
+ * hb_subset_cff1:
+ * Subsets the CFF table according to a provided plan.
+ *
+ * Return value: subsetted cff table.
+ **/
+bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+               hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source);
+  const char *data = hb_blob_get_data(cff_blob, nullptr);
+
+  OT::cff1::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+                       _hb_subset_cff1 (acc, data, plan, prime);
+  hb_blob_destroy (cff_blob);
+  acc.fini ();
+
+  return result;
+}
diff --git a/src/hb-subset-cff1.hh b/src/hb-subset-cff1.hh
new file mode 100644 (file)
index 0000000..1ec8678
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF1_HH
+#define HB_SUBSET_CFF1_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+              hb_blob_t        **cff_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF1_HH */
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
new file mode 100644 (file)
index 0000000..73a292d
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff2.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff2_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      varStoreOffset (0)
+  {}
+
+  unsigned int  varStoreOffset;
+};
+
+struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
+{
+  bool serialize (hb_serialize_context_t *c,
+                 const op_str_t &opstr,
+                 const cff2_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+       return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.varStoreOffset));
+
+      default:
+       return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, offsets));
+    }
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+       return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+       return cff_top_dict_op_serializer_t<>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+       /* dummy opcodes in CFF2. ignore */
+       break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+       if (param.drop_hints)
+       {
+         env.clear_args ();
+         return;
+       }
+       HB_FALLTHROUGH;
+
+      default:
+       SUPER::flush_args_and_op (op, env, param);
+       break;
+    }
+  }
+
+  static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    for (unsigned int i = 0; i < env.argStack.get_count ();)
+    {
+      const blend_arg_t &arg = env.argStack[i];
+      if (arg.blending ())
+      {
+       if (unlikely (!((arg.numValues > 0) && (env.argStack.get_count () >= arg.numValues))))
+       {
+         env.set_error ();
+         return;
+       }
+       flatten_blends (arg, i, env, param);
+       i += arg.numValues;
+      }
+      else
+      {
+       str_encoder_t  encoder (param.flatStr);
+       encoder.encode_num (arg);
+       i++;
+      }
+    }
+    SUPER::flush_args (env, param);
+  }
+
+  static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    /* flatten the default values */
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      if (unlikely (!((arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
+             (arg1.deltas.length == env.get_region_count ())))))
+      {
+       env.set_error ();
+       return;
+      }
+      encoder.encode_num (arg1);
+    }
+    /* flatten deltas for each value */
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      for (unsigned int k = 0; k < arg1.deltas.length; k++)
+       encoder.encode_num (arg1.deltas[k]);
+    }
+    /* flatten the number of values followed by blend operator */
+    encoder.encode_int (arg.numValues);
+    encoder.encode_op (OpCode_blendcs);
+  }
+
+  static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+       return;
+      default:
+       str_encoder_t  encoder (param.flatStr);
+       encoder.encode_op (op);
+    }
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t> SUPER;
+  typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+};
+
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+       param.current_parsed_str->set_parsed ();
+       env.returnFromSubr ();
+       param.set_current_str (env, false);
+       break;
+
+      case OpCode_endchar:
+       param.current_parsed_str->set_parsed ();
+       SUPER::process_op (op, env, param);
+       break;
+
+      case OpCode_callsubr:
+       process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+       break;
+
+      case OpCode_callgsubr:
+       process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+       break;
+
+      default:
+       SUPER::process_op (op, env, param);
+       param.current_parsed_str->add_op (op, env.str_ref);
+       break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+                                cff2_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* vsindex is inserted at the beginning of the charstring as necessary */
+    if (env.seen_vsindex ())
+    {
+      number_t  ivs;
+      ivs.set_int ((int)env.get_ivs ());
+      charstring.set_prefix (ivs, OpCode_vsindexcs);
+    }
+  }
+};
+
+struct cff2_subset_plan {
+  cff2_subset_plan ()
+    : final_size (0),
+      orig_fdcount (0),
+      subset_fdcount(1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize (false)
+  {
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    privateDictInfos.init ();
+  }
+
+  ~cff2_subset_plan ()
+  {
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    privateDictInfos.fini ();
+  }
+
+  bool create (const OT::cff2::accelerator_subset_t &acc,
+             hb_subset_plan_t *plan)
+  {
+    final_size = 0;
+    orig_fdcount = acc.fdArray->count;
+
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* CFF2 header */
+    final_size += OT::cff2::static_size;
+
+    /* top dict */
+    {
+      cff2_top_dict_op_serializer_t topSzr;
+      offsets.topDictInfo.size = TopDict::calculate_serialized_size (acc.topDict, topSzr);
+      final_size += offsets.topDictInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+                   flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+       return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+       return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+       return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+       return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+       return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+       return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+       subset_localsubrs[fd].init ();
+       offsets.localSubrsInfos[fd].init ();
+       if (fdmap.includes (fd))
+       {
+         if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+           return false;
+
+         unsigned int dataSize = subset_localsubrs[fd].total_size ();
+         if (dataSize > 0)
+         {
+           offsets.localSubrsInfos[fd].offset = final_size;
+           offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+           offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+         }
+       }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* variation store */
+    if (acc.varStore != &Null(CFF2VariationStore))
+    {
+      offsets.varStoreOffset = final_size;
+      final_size += acc.varStore->get_size ();
+    }
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF2FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                 orig_fdcount,
+                                 *(const FDSelect *)acc.fdSelect,
+                                 subset_fdcount,
+                                 offsets.FDSelectInfo.size,
+                                 subset_fdselect_format,
+                                 subset_fdselect_ranges,
+                                 fdmap)))
+       return false;
+
+      final_size += offsets.FDSelectInfo.size;
+    }
+    else
+      fdmap.identity (1);
+
+    /* FDArray (FDIndex) */
+    {
+      offsets.FDArrayInfo.offset = final_size;
+      cff_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+       if (fdmap.includes (i))
+         dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictsOffset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+       bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+       cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
+       unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+       table_info_t  privInfo = { final_size, priv_size, 0 };
+       privateDictInfos.push (privInfo);
+       final_size += privInfo.size;
+
+       if (!plan->desubroutinize && has_localsubrs)
+       {
+         offsets.localSubrsInfos[i].offset = final_size;
+         final_size += offsets.localSubrsInfos[i].size;
+       }
+      }
+    }
+
+    return true;
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int final_size;
+  cff2_sub_table_offsets_t offsets;
+
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  remap_t   fdmap;
+
+  str_buff_vec_t           subset_charstrings;
+  str_buff_vec_t           subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t> subset_localsubrs;
+  hb_vector_t<table_info_t>  privateDictInfos;
+
+  bool     drop_hints;
+  bool     desubroutinize;
+  cff2_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff2 (const cff2_subset_plan &plan,
+                               const OT::cff2::accelerator_subset_t  &acc,
+                               const hb_vector_t<hb_codepoint_t>& glyphs,
+                               unsigned int dest_sz,
+                               void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
+  if (unlikely (!c.extend_min (*cff2)))
+    return false;
+
+  /* header */
+  cff2->version.major.set (0x02);
+  cff2->version.minor.set (0x00);
+  cff2->topDict.set (OT::cff2::static_size);
+
+  /* top dict */
+  {
+    assert (cff2->topDict == (unsigned) (c.head - c.start));
+    cff2->topDictSize.set (plan.offsets.topDictInfo.size);
+    TopDict &dict = cff2 + cff2->topDict;
+    cff2_top_dict_op_serializer_t topSzr;
+    if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c.head - c.start));
+    CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* variation store */
+  if (acc.varStore != &Null(CFF2VariationStore))
+  {
+    assert (plan.offsets.varStoreOffset == (unsigned) (c.head - c.start));
+    CFF2VariationStore *dest = c.start_embed<CFF2VariationStore> ();
+    if (unlikely (!dest->serialize (&c, acc.varStore)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF2FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
+                                             plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                             plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF2FDArray  *fda = c.start_embed<CFF2FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                  acc.fontDicts, plan.subset_fdcount, plan.fdmap,
+                                  fontSzr, plan.privateDictInfos)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF2CharStrings  *cs = c.start_embed<CFF2CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+       DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+       return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+       CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+       if (unlikely (dest == nullptr)) return false;
+       if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+       {
+         DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+         return false;
+       }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
+               const char                    *data,
+               hb_subset_plan_t                *plan,
+               hb_blob_t                      **prime /* OUT */)
+{
+  cff2_subset_plan cff2_plan;
+
+  if (unlikely (!cff2_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff2_prime_size = cff2_plan.get_final_size ();
+  char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
+
+  if (unlikely (!_write_cff2 (cff2_plan, acc, plan->glyphs,
+                             cff2_prime_size, cff2_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
+    free (cff2_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff2_prime_data,
+                               cff2_prime_size,
+                               HB_MEMORY_MODE_READONLY,
+                               cff2_prime_data,
+                               free);
+  return true;
+}
+
+/**
+ * hb_subset_cff2:
+ * Subsets the CFF2 table according to a provided plan.
+ *
+ * Return value: subsetted cff2 table.
+ **/
+bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+               hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
+  const char *data = hb_blob_get_data(cff2_blob, nullptr);
+
+  OT::cff2::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+               _hb_subset_cff2 (acc, data, plan, prime);
+
+  hb_blob_destroy (cff2_blob);
+  acc.fini ();
+
+  return result;
+}
diff --git a/src/hb-subset-cff2.hh b/src/hb-subset-cff2.hh
new file mode 100644 (file)
index 0000000..a07dc29
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF2_HH
+#define HB_SUBSET_CFF2_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+              hb_blob_t       **cff2_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF2_HH */
index c8fa39b..cca364d 100644 (file)
  * Google Author(s): Garret Rieger, Roderick Sheeter
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-set.h"
 #include "hb-subset-glyf.hh"
-#include "hb-subset-plan.hh"
 
 static bool
 _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
-                                     hb_vector_t<hb_codepoint_t> &glyph_ids,
-                                     hb_bool_t drop_hints,
-                                     bool *use_short_loca /* OUT */,
-                                     unsigned int *glyf_size /* OUT */,
-                                     unsigned int *loca_size /* OUT */,
-                                     hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
+                                    hb_vector_t<hb_codepoint_t> &glyph_ids,
+                                    hb_bool_t drop_hints,
+                                    bool *use_short_loca /* OUT */,
+                                    unsigned int *glyf_size /* OUT */,
+                                    unsigned int *loca_size /* OUT */,
+                                    hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
 {
   unsigned int total = 0;
-  for (unsigned int i = 0; i < glyph_ids.len; i++)
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
   {
     hb_codepoint_t next_glyph = glyph_ids[i];
-    if (!instruction_ranges->resize (instruction_ranges->len + 2))
+    if (!instruction_ranges->resize (instruction_ranges->length + 2))
     {
       DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
       return false;
     }
-    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->len - 2];
+    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
     *instruction_start = 0;
-    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->len - 1];
+    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
     *instruction_end = 0;
 
     unsigned int start_offset, end_offset;
-    if (unlikely (!(glyf.get_offsets(next_glyph, &start_offset, &end_offset)
-                    && glyf.remove_padding(start_offset, &end_offset))))
+    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
+                   glyf.remove_padding (start_offset, &end_offset))))
     {
       DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
       continue;
@@ -65,11 +64,11 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
 
     if (drop_hints)
     {
-      if (unlikely (!glyf.get_instruction_offsets(start_offset, end_offset,
-                                                  instruction_start, instruction_end)))
+      if (unlikely (!glyf.get_instruction_offsets (start_offset, end_offset,
+                                                  instruction_start, instruction_end)))
       {
-        DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
-        return false;
+       DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
+       return false;
       }
     }
 
@@ -80,22 +79,22 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
 
   *glyf_size = total;
   *use_short_loca = (total <= 131070);
-  *loca_size = (glyph_ids.len + 1)
-      * (*use_short_loca ? sizeof(OT::HBUINT16) : sizeof(OT::HBUINT32));
+  *loca_size = (glyph_ids.length + 1)
+      * (*use_short_loca ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
 
   DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
-            total,
-            *loca_size,
-            *use_short_loca ? "short" : "long");
+           total,
+           *loca_size,
+           *use_short_loca ? "short" : "long");
   return true;
 }
 
 static bool
 _write_loca_entry (unsigned int  id,
-                   unsigned int  offset,
-                   bool          is_short,
-                   void         *loca_prime,
-                   unsigned int  loca_size)
+                  unsigned int  offset,
+                  bool          is_short,
+                  void         *loca_prime,
+                  unsigned int  loca_size)
 {
   unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
   if ((id + 1) * entry_size <= loca_size)
@@ -109,11 +108,11 @@ _write_loca_entry (unsigned int  id,
   }
 
   // Offset was not written because the write is out of bounds.
-  DEBUG_MSG (SUBSET,
-             nullptr,
-             "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
-             id,
-             loca_size);
+  DEBUG_MSG(SUBSET,
+           nullptr,
+           "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
+           id,
+           loca_size);
   return false;
 }
 
@@ -131,15 +130,15 @@ _update_components (hb_subset_plan_t * plan,
     {
       hb_codepoint_t new_gid;
       if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
-                                      &new_gid))
+                                     &new_gid))
        continue;
 
       ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
-    } while (iterator.move_to_next());
+    } while (iterator.move_to_next ());
   }
 }
 
-static bool _remove_composite_instruction_flag(char *glyf_prime, unsigned int length)
+static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
 {
   /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
   OT::glyf::CompositeGlyphHeader::Iterator composite_it;
@@ -149,30 +148,30 @@ static bool _remove_composite_instruction_flag(char *glyf_prime, unsigned int le
     glyph = composite_it.current;
     OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
     flags->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS);
-  } while (composite_it.move_to_next());
+  } while (composite_it.move_to_next ());
   return true;
 }
 
 static bool
 _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
                            const OT::glyf::accelerator_t &glyf,
-                            const char                    *glyf_data,
-                            bool                           use_short_loca,
-                            hb_vector_t<unsigned int> &instruction_ranges,
-                            unsigned int                   glyf_prime_size,
-                            char                          *glyf_prime_data /* OUT */,
-                            unsigned int                   loca_prime_size,
-                            char                          *loca_prime_data /* OUT */)
+                           const char                    *glyf_data,
+                           bool                           use_short_loca,
+                           hb_vector_t<unsigned int> &instruction_ranges,
+                           unsigned int                   glyf_prime_size,
+                           char                          *glyf_prime_data /* OUT */,
+                           unsigned int                   loca_prime_size,
+                           char                          *loca_prime_data /* OUT */)
 {
   hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
   char *glyf_prime_data_next = glyf_prime_data;
 
   bool success = true;
-  for (unsigned int i = 0; i < glyph_ids.len; i++)
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
   {
     unsigned int start_offset, end_offset;
-    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)
-                    && glyf.remove_padding(start_offset, &end_offset))))
+    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
+                   glyf.remove_padding (start_offset, &end_offset))))
       end_offset = start_offset = 0;
 
     unsigned int instruction_start = instruction_ranges[i * 2];
@@ -182,10 +181,10 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
 
     if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
     {
-      DEBUG_MSG (SUBSET,
-                 nullptr,
-                 "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
-                 i, length);
+      DEBUG_MSG(SUBSET,
+                nullptr,
+                "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
+                i, length);
       return false;
     }
 
@@ -198,39 +197,39 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
       /* if the instructions end at the end this was a composite glyph, else simple */
       if (instruction_end == end_offset)
       {
-        if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
+       if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
       }
       else
-        /* zero instruction length, which is just before instruction_start */
-        memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
+       /* zero instruction length, which is just before instruction_start */
+       memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
     }
 
     success = success && _write_loca_entry (i,
-                                            glyf_prime_data_next - glyf_prime_data,
-                                            use_short_loca,
-                                            loca_prime_data,
-                                            loca_prime_size);
+                                           glyf_prime_data_next - glyf_prime_data,
+                                           use_short_loca,
+                                           loca_prime_data,
+                                           loca_prime_size);
     _update_components (plan, glyf_prime_data_next, length);
 
     // TODO: don't align to two bytes if using long loca.
     glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
   }
 
-  success = success && _write_loca_entry (glyph_ids.len,
-                                          glyf_prime_data_next - glyf_prime_data,
-                                          use_short_loca,
-                                          loca_prime_data,
-                                          loca_prime_size);
+  success = success && _write_loca_entry (glyph_ids.length,
+                                         glyf_prime_data_next - glyf_prime_data,
+                                         use_short_loca,
+                                         loca_prime_data,
+                                         loca_prime_size);
   return success;
 }
 
 static bool
 _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
-                          const char                     *glyf_data,
-                          hb_subset_plan_t               *plan,
-                          bool                           *use_short_loca,
-                          hb_blob_t                     **glyf_prime /* OUT */,
-                          hb_blob_t                     **loca_prime /* OUT */)
+                         const char                     *glyf_data,
+                         hb_subset_plan_t               *plan,
+                         bool                           *use_short_loca,
+                         hb_blob_t                     **glyf_prime /* OUT */,
+                         hb_blob_t                     **loca_prime /* OUT */)
 {
   // TODO(grieger): Sanity check allocation size for the new table.
   hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
@@ -238,43 +237,43 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
   unsigned int glyf_prime_size;
   unsigned int loca_prime_size;
   hb_vector_t<unsigned int> instruction_ranges;
-  instruction_ranges.init();
+  instruction_ranges.init ();
 
   if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
-                                                      glyphs_to_retain,
-                                                      plan->drop_hints,
-                                                      use_short_loca,
-                                                      &glyf_prime_size,
-                                                      &loca_prime_size,
-                                                      &instruction_ranges))) {
-    instruction_ranges.fini();
+                                                     glyphs_to_retain,
+                                                     plan->drop_hints,
+                                                     use_short_loca,
+                                                     &glyf_prime_size,
+                                                     &loca_prime_size,
+                                                     &instruction_ranges))) {
+    instruction_ranges.fini ();
     return false;
   }
 
   char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
   char *loca_prime_data = (char *) calloc (1, loca_prime_size);
   if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
-                                             *use_short_loca,
-                                             instruction_ranges,
-                                             glyf_prime_size, glyf_prime_data,
-                                             loca_prime_size, loca_prime_data))) {
+                                            *use_short_loca,
+                                            instruction_ranges,
+                                            glyf_prime_size, glyf_prime_data,
+                                            loca_prime_size, loca_prime_data))) {
     free (glyf_prime_data);
     free (loca_prime_data);
-    instruction_ranges.fini();
+    instruction_ranges.fini ();
     return false;
   }
-  instruction_ranges.fini();
+  instruction_ranges.fini ();
 
   *glyf_prime = hb_blob_create (glyf_prime_data,
-                                glyf_prime_size,
-                                HB_MEMORY_MODE_READONLY,
-                                glyf_prime_data,
-                                free);
+                               glyf_prime_size,
+                               HB_MEMORY_MODE_READONLY,
+                               glyf_prime_data,
+                               free);
   *loca_prime = hb_blob_create (loca_prime_data,
-                                loca_prime_size,
-                                HB_MEMORY_MODE_READONLY,
-                                loca_prime_data,
-                                free);
+                               loca_prime_size,
+                               HB_MEMORY_MODE_READONLY,
+                               loca_prime_data,
+                               free);
   return true;
 }
 
@@ -288,24 +287,24 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
  **/
 bool
 hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
-                         bool             *use_short_loca, /* OUT */
-                         hb_blob_t       **glyf_prime, /* OUT */
-                         hb_blob_t       **loca_prime /* OUT */)
+                        bool             *use_short_loca, /* OUT */
+                        hb_blob_t       **glyf_prime, /* OUT */
+                        hb_blob_t       **loca_prime /* OUT */)
 {
-  hb_blob_t *glyf_blob = OT::Sanitizer<OT::glyf>().sanitize (plan->source->reference_table (HB_OT_TAG_glyf));
-  const char *glyf_data = hb_blob_get_data(glyf_blob, nullptr);
+  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
+  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);
 
   OT::glyf::accelerator_t glyf;
-  glyf.init(plan->source);
+  glyf.init (plan->source);
   bool result = _hb_subset_glyf_and_loca (glyf,
-                                          glyf_data,
-                                          plan,
-                                          use_short_loca,
-                                          glyf_prime,
-                                          loca_prime);
+                                         glyf_data,
+                                         plan,
+                                         use_short_loca,
+                                         glyf_prime,
+                                         loca_prime);
 
   hb_blob_destroy (glyf_blob);
-  glyf.fini();
+  glyf.fini ();
 
   return result;
 }
index 99b76db..99cf8f0 100644 (file)
 #ifndef HB_SUBSET_GLYF_HH
 #define HB_SUBSET_GLYF_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-subset-plan.hh"
+#include "hb-subset.hh"
 
 HB_INTERNAL bool
 hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
-                         bool             *use_short_loca, /* OUT */
-                         hb_blob_t       **glyf_prime /* OUT */,
-                         hb_blob_t       **loca_prime /* OUT */);
+                        bool             *use_short_loca, /* OUT */
+                        hb_blob_t       **glyf_prime      /* OUT */,
+                        hb_blob_t       **loca_prime      /* OUT */);
 
 #endif /* HB_SUBSET_GLYF_HH */
index 39c5ac4..f718a56 100644 (file)
@@ -24,9 +24,8 @@
  * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
  */
 
-#include "hb-object-private.hh"
-#include "hb-subset-private.hh"
-#include "hb-set-private.hh"
+#include "hb-subset.hh"
+#include "hb-set.hh"
 
 /**
  * hb_subset_input_create_or_fail:
@@ -36,7 +35,7 @@
  * Since: 1.8.0
  **/
 hb_subset_input_t *
-hb_subset_input_create_or_fail (void)
+hb_subset_input_create_or_fail ()
 {
   hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
 
@@ -45,7 +44,7 @@ hb_subset_input_create_or_fail (void)
 
   input->unicodes = hb_set_create ();
   input->glyphs = hb_set_create ();
-  input->drop_ot_layout = true;
+  input->drop_layout = true;
 
   return input;
 }
@@ -73,7 +72,7 @@ hb_subset_input_reference (hb_subset_input_t *subset_input)
  * Since: 1.8.0
  **/
 void
-hb_subset_input_destroy(hb_subset_input_t *subset_input)
+hb_subset_input_destroy (hb_subset_input_t *subset_input)
 {
   if (!hb_object_destroy (subset_input)) return;
 
@@ -107,30 +106,41 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
   return subset_input->glyphs;
 }
 
-/**
- * hb_subset_input_drop_hints:
- * @subset_input: a subset_input.
- *
- * Since: 1.8.0
- **/
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints (hb_subset_input_t *subset_input)
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                               hb_bool_t drop_hints)
 {
-  return &subset_input->drop_hints;
+  subset_input->drop_hints = drop_hints;
 }
 
-/**
- * hb_subset_input_drop_ot_layout:
- * @subset_input: a subset_input.
- *
- * If enabled ot layout tables will be dropped as part of
- * the subsetting operation. Currently this defaults to
- * true.
- *
- * Since: REPLACEME
- **/
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input)
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_hints;
+}
+
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_layout)
+{
+  subset_input->drop_layout = drop_layout;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_layout;
+}
+
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize)
+{
+  subset_input->desubroutinize = desubroutinize;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
 {
-  return &subset_input->drop_ot_layout;
+  return subset_input->desubroutinize;
 }
diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh
new file mode 100644 (file)
index 0000000..8dad94f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_INPUT_HH
+#define HB_SUBSET_INPUT_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-font.hh"
+
+struct hb_subset_input_t
+{
+  hb_object_header_t header;
+
+  hb_set_t *unicodes;
+  hb_set_t *glyphs;
+
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
+  /* TODO
+   *
+   * features
+   * lookups
+   * nameIDs
+   * ...
+   */
+};
+
+
+#endif /* HB_SUBSET_INPUT_HH */
index 55c4e3f..cff3426 100644 (file)
  * Google Author(s): Garret Rieger, Roderick Sheeter
  */
 
-#include "hb-map-private.hh"
-#include "hb-subset-private.hh"
-#include "hb-set-private.hh"
-
 #include "hb-subset-plan.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
 
 static void
 _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
@@ -54,29 +54,59 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
 }
 
 static void
+_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
+           hb_codepoint_t gid,
+           hb_set_t *gids_to_retain)
+{
+  hb_codepoint_t base_gid, accent_gid;
+  if (cff.get_seac_components (gid, &base_gid, &accent_gid))
+  {
+    hb_set_add (gids_to_retain, base_gid);
+    hb_set_add (gids_to_retain, accent_gid);
+  }
+}
+
+static void
 _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
 {
-  // TODO(grieger): This uses all lookups, instead collect
-  //                the set of lookups that are relevant.
-  //                See fontTools implementation.
+  hb_set_t lookup_indices;
+  hb_ot_layout_collect_lookups (face,
+                               HB_OT_TAG_GSUB,
+                               nullptr,
+                               nullptr,
+                               nullptr,
+                               &lookup_indices);
   hb_ot_layout_lookups_substitute_closure (face,
-                                           nullptr,
-                                           gids_to_retain);
+                                          &lookup_indices,
+                                          gids_to_retain);
 }
 
-
 static void
+_remove_invalid_gids (hb_set_t *glyphs,
+                     unsigned int num_glyphs)
+{
+  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
+  while (glyphs->next (&gid))
+  {
+    if (gid >= num_glyphs)
+      glyphs->del (gid);
+  }
+}
+
+static hb_set_t *
 _populate_gids_to_retain (hb_face_t *face,
-                          const hb_set_t *unicodes,
-                          bool close_over_gsub,
-                          hb_set_t *unicodes_to_retain,
-                          hb_map_t *codepoint_to_glyph,
-                          hb_vector_t<hb_codepoint_t> *glyphs)
+                         const hb_set_t *unicodes,
+                         bool close_over_gsub,
+                         hb_set_t *unicodes_to_retain,
+                         hb_map_t *codepoint_to_glyph,
+                         hb_vector_t<hb_codepoint_t> *glyphs)
 {
   OT::cmap::accelerator_t cmap;
   OT::glyf::accelerator_t glyf;
+  OT::cff1::accelerator_t cff;
   cmap.init (face);
   glyf.init (face);
+  cff.init (face);
 
   hb_set_t *initial_gids_to_retain = hb_set_create ();
   initial_gids_to_retain->add (0); // Not-def
@@ -106,24 +136,30 @@ _populate_gids_to_retain (hb_face_t *face,
   while (initial_gids_to_retain->next (&gid))
   {
     _add_gid_and_children (glyf, gid, all_gids_to_retain);
+    if (cff.is_valid ())
+      _add_cff_seac_components (cff, gid, all_gids_to_retain);
   }
   hb_set_destroy (initial_gids_to_retain);
 
+  _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ());
+
   glyphs->alloc (all_gids_to_retain->get_population ());
   gid = HB_SET_VALUE_INVALID;
   while (all_gids_to_retain->next (&gid))
     glyphs->push (gid);
 
-  hb_set_destroy (all_gids_to_retain);
+  cff.fini ();
   glyf.fini ();
   cmap.fini ();
+
+  return all_gids_to_retain;
 }
 
 static void
 _create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
-                                hb_map_t *glyph_map)
+                               hb_map_t *glyph_map)
 {
-  for (unsigned int i = 0; i < glyphs.len; i++) {
+  for (unsigned int i = 0; i < glyphs.length; i++) {
     glyph_map->set (glyphs[i], i);
   }
 }
@@ -131,7 +167,7 @@ _create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
 /**
  * hb_subset_plan_create:
  * Computes a plan for subsetting the supplied face according
- * to a provide profile and input. The plan describes
+ * to a provided input. The plan describes
  * which tables and glyphs should be retained.
  *
  * Return value: New subset plan.
@@ -140,28 +176,27 @@ _create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
  **/
 hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_profile_t *profile,
-                       hb_subset_input_t   *input)
+                      hb_subset_input_t   *input)
 {
   hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
 
   plan->drop_hints = input->drop_hints;
-  plan->drop_ot_layout = input->drop_ot_layout;
+  plan->drop_layout = input->drop_layout;
+  plan->desubroutinize = input->desubroutinize;
   plan->unicodes = hb_set_create();
   plan->glyphs.init();
   plan->source = hb_face_reference (face);
-  plan->dest = hb_subset_face_create ();
+  plan->dest = hb_face_builder_create ();
   plan->codepoint_to_glyph = hb_map_create();
   plan->glyph_map = hb_map_create();
-
-  _populate_gids_to_retain (face,
-                            input->unicodes,
-                            !plan->drop_ot_layout,
-                            plan->unicodes,
-                            plan->codepoint_to_glyph,
-                            &plan->glyphs);
+  plan->glyphset = _populate_gids_to_retain (face,
+                                            input->unicodes,
+                                            !plan->drop_layout,
+                                            plan->unicodes,
+                                            plan->codepoint_to_glyph,
+                                            &plan->glyphs);
   _create_old_gid_to_new_gid_map (plan->glyphs,
-                                  plan->glyph_map);
+                                 plan->glyph_map);
 
   return plan;
 }
@@ -177,11 +212,12 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
   if (!hb_object_destroy (plan)) return;
 
   hb_set_destroy (plan->unicodes);
-  plan->glyphs.fini();
+  plan->glyphs.fini ();
   hb_face_destroy (plan->source);
   hb_face_destroy (plan->dest);
   hb_map_destroy (plan->codepoint_to_glyph);
   hb_map_destroy (plan->glyph_map);
+  hb_set_destroy (plan->glyphset);
 
   free (plan);
 }
index f4b261d..a710a4d 100644 (file)
 #ifndef HB_SUBSET_PLAN_HH
 #define HB_SUBSET_PLAN_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-subset.h"
-#include "hb-subset-private.hh"
+#include "hb-subset-input.hh"
 
-#include "hb-object-private.hh"
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 struct hb_subset_plan_t
 {
   hb_object_header_t header;
-  ASSERT_POD ();
 
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
 
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
-  // This list contains the complete set of glyphs to retain and may contain
-  // more glyphs then the lists above.
   hb_vector_t<hb_codepoint_t> glyphs;
+  hb_set_t *glyphset;
 
   hb_map_t *codepoint_to_glyph;
   hb_map_t *glyph_map;
@@ -57,9 +55,8 @@ struct hb_subset_plan_t
   hb_face_t *source;
   hb_face_t *dest;
 
-  inline hb_bool_t
-  new_gid_for_codepoint (hb_codepoint_t codepoint,
-                         hb_codepoint_t *new_gid) const
+  bool new_gid_for_codepoint (hb_codepoint_t codepoint,
+                             hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
     if (old_gid == HB_MAP_VALUE_INVALID)
@@ -68,9 +65,8 @@ struct hb_subset_plan_t
     return new_gid_for_old_gid (old_gid, new_gid);
   }
 
-  inline hb_bool_t
-  new_gid_for_old_gid (hb_codepoint_t old_gid,
-                      hb_codepoint_t *new_gid) const
+  bool new_gid_for_old_gid (hb_codepoint_t old_gid,
+                           hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t gid = glyph_map->get (old_gid);
     if (gid == HB_MAP_VALUE_INVALID)
@@ -80,17 +76,17 @@ struct hb_subset_plan_t
     return true;
   }
 
-  inline hb_bool_t
+  bool
   add_table (hb_tag_t tag,
-             hb_blob_t *contents)
+            hb_blob_t *contents)
   {
     hb_blob_t *source_blob = source->reference_table (tag);
     DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
-              HB_UNTAG(tag),
-              hb_blob_get_length (contents),
-              hb_blob_get_length (source_blob));
+             HB_UNTAG(tag),
+             hb_blob_get_length (contents),
+             hb_blob_get_length (source_blob));
     hb_blob_destroy (source_blob);
-    return hb_subset_face_add_table(dest, tag, contents);
+    return hb_face_builder_add_table (dest, tag, contents);
   }
 };
 
@@ -98,7 +94,6 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
 
 HB_INTERNAL hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
 HB_INTERNAL void
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
deleted file mode 100644 (file)
index 6b2b207..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger, Roderick Sheeter
- */
-
-#ifndef HB_SUBSET_PRIVATE_HH
-#define HB_SUBSET_PRIVATE_HH
-
-
-#include "hb-private.hh"
-
-#include "hb-subset.h"
-
-#include "hb-font-private.hh"
-
-typedef struct hb_subset_face_data_t hb_subset_face_data_t;
-
-struct hb_subset_input_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_set_t *unicodes;
-  hb_set_t *glyphs;
-
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
-  /* TODO
-   *
-   * features
-   * lookups
-   * nameIDs
-   * ...
-   */
-};
-
-HB_INTERNAL hb_face_t *
-hb_subset_face_create (void);
-
-HB_INTERNAL hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob);
-
-#endif /* HB_SUBSET_PRIVATE_HH */
index b97c763..37e7cec 100644 (file)
  * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-open-type-private.hh"
+#include "hb.hh"
+#include "hb-open-type.hh"
 
+#include "hb-subset.hh"
 #include "hb-subset-glyf.hh"
-#include "hb-subset-private.hh"
-#include "hb-subset-plan.hh"
 
-#include "hb-open-file-private.hh"
+#include "hb-open-file.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-hdmx-table.hh"
 #include "hb-ot-maxp-table.hh"
 #include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-vorg-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
 
 
-struct hb_subset_profile_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-};
-
-/**
- * hb_subset_profile_create:
- *
- * Return value: New profile with default settings.
- *
- * Since: 1.8.0
- **/
-hb_subset_profile_t *
-hb_subset_profile_create ()
+static unsigned int
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+                                 unsigned int table_len)
 {
-  return hb_object_create<hb_subset_profile_t>();
-}
+  unsigned int src_glyphs = plan->source->get_num_glyphs ();
+  unsigned int dst_glyphs = plan->glyphset->get_population ();
 
-/**
- * hb_subset_profile_destroy:
- *
- * Since: 1.8.0
- **/
-void
-hb_subset_profile_destroy (hb_subset_profile_t *profile)
-{
-  if (!hb_object_destroy (profile)) return;
+  if (unlikely (!src_glyphs))
+    return 512 + table_len;
 
-  free (profile);
+  return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
 }
 
 template<typename TableType>
 static bool
-_subset (hb_subset_plan_t *plan)
+_subset2 (hb_subset_plan_t *plan)
 {
-  OT::Sanitizer<TableType> sanitizer;
-
-  hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag));
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
   const TableType *table = source_blob->as<TableType> ();
 
   hb_tag_t tag = TableType::tableTag;
   hb_bool_t result = false;
-  if (table != &Null(TableType))
-  {
-    result = table->subset(plan);
-  } else {
-    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG(tag));
-  }
-
-  hb_blob_destroy (source_blob);
-  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!");
-  return result;
-}
-
-
-/*
- * A face that has add_table().
- */
-
-struct hb_subset_face_data_t
-{
-  struct table_entry_t
+  if (source_blob->data)
   {
-    inline int cmp (const hb_tag_t *t) const
+    hb_vector_t<char> buf;
+    unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+    if (unlikely (!buf.alloc (buf_size)))
     {
-      if (*t < tag) return -1;
-      if (*t > tag) return -1;
-      return 0;
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+      return false;
+    }
+  retry:
+    hb_serialize_context_t serializer ((void *) buf, buf_size);
+    hb_subset_context_t c (plan, &serializer);
+    result = table->subset (&c);
+    if (serializer.in_error ())
+    {
+      buf_size += (buf_size >> 1) + 32;
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
+      if (unlikely (!buf.alloc (buf_size)))
+      {
+       DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
+       return false;
+      }
+      goto retry;
+    }
+    if (result)
+    {
+      hb_blob_t *dest_blob = serializer.copy_blob ();
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
+      result = c.plan->add_table (tag, dest_blob);
+      hb_blob_destroy (dest_blob);
+    }
+    else
+    {
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+      result = true;
     }
-
-    hb_tag_t   tag;
-    hb_blob_t *blob;
-  };
-
-  hb_vector_t<table_entry_t, 32> tables;
-};
-
-static hb_subset_face_data_t *
-_hb_subset_face_data_create (void)
-{
-  hb_subset_face_data_t *data = (hb_subset_face_data_t *) calloc (1, sizeof (hb_subset_face_data_t));
-  if (unlikely (!data))
-    return nullptr;
-
-  data->tables.init ();
-
-  return data;
-}
-
-static void
-_hb_subset_face_data_destroy (void *user_data)
-{
-  hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
-
-  for (unsigned int i = 0; i < data->tables.len; i++)
-    hb_blob_destroy (data->tables[i].blob);
-
-  data->tables.fini ();
-
-  free (data);
-}
-
-static hb_blob_t *
-_hb_subset_face_data_reference_blob (hb_subset_face_data_t *data)
-{
-
-  unsigned int table_count = data->tables.len;
-  unsigned int face_length = table_count * 16 + 12;
-
-  for (unsigned int i = 0; i < table_count; i++)
-    face_length += _hb_ceil_to_4 (hb_blob_get_length (data->tables.arrayZ[i].blob));
-
-  char *buf = (char *) malloc (face_length);
-  if (unlikely (!buf))
-    return nullptr;
-
-  OT::hb_serialize_context_t c (buf, face_length);
-  OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
-
-  bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
-  hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
-
-  OT::Supplier<hb_tag_t>    tags_supplier  (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
-  OT::Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
-  bool ret = f->serialize_single (&c,
-                                 sfnt_tag,
-                                 tags_supplier,
-                                 blobs_supplier,
-                                 table_count);
-
-  c.end_serialize ();
-
-  if (unlikely (!ret))
-  {
-    free (buf);
-    return nullptr;
   }
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
 
-  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
 }
 
-static hb_blob_t *
-_hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+template<typename TableType>
+static bool
+_subset (hb_subset_plan_t *plan)
 {
-  hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
-
-  if (!tag)
-    return _hb_subset_face_data_reference_blob (data);
-
-  hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (tag);
-  if (entry)
-    return hb_blob_reference (entry->blob);
-
-  return nullptr;
-}
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
+  const TableType *table = source_blob->as<TableType> ();
 
-/* TODO: Move this to hb-face.h and rename to hb_face_builder_create()
- * with hb_face_builder_add_table(). */
-hb_face_t *
-hb_subset_face_create (void)
-{
-  hb_subset_face_data_t *data = _hb_subset_face_data_create ();
-  if (unlikely (!data)) return hb_face_get_empty ();
+  hb_tag_t tag = TableType::tableTag;
+  hb_bool_t result = false;
+  if (source_blob->data)
+    result = table->subset (plan);
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
 
-  return hb_face_create_for_tables (_hb_subset_face_reference_table,
-                                   data,
-                                   _hb_subset_face_data_destroy);
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
 }
 
-hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
-{
-  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_subset_face_data_destroy))
-    return false;
-
-  hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data;
-  hb_subset_face_data_t::table_entry_t *entry = data->tables.push ();
-
-  entry->tag = tag;
-  entry->blob = hb_blob_reference (blob);
-
-  return true;
-}
 
 static bool
 _subset_table (hb_subset_plan_t *plan,
-               hb_tag_t          tag)
+              hb_tag_t          tag)
 {
-  DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG(tag));
+  DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
   bool result = true;
   switch (tag) {
     case HB_OT_TAG_glyf:
@@ -267,27 +174,46 @@ _subset_table (hb_subset_plan_t *plan,
     case HB_OT_TAG_cmap:
       result = _subset<const OT::cmap> (plan);
       break;
-    case HB_OT_TAG_os2:
-      result = _subset<const OT::os2> (plan);
+    case HB_OT_TAG_OS2:
+      result = _subset<const OT::OS2> (plan);
       break;
     case HB_OT_TAG_post:
       result = _subset<const OT::post> (plan);
       break;
+    case HB_OT_TAG_cff1:
+      result = _subset<const OT::cff1> (plan);
+      break;
+    case HB_OT_TAG_cff2:
+      result = _subset<const OT::cff2> (plan);
+      break;
+    case HB_OT_TAG_VORG:
+      result = _subset<const OT::VORG> (plan);
+      break;
+    case HB_OT_TAG_GDEF:
+      result = _subset2<const OT::GDEF> (plan);
+      break;
+    case HB_OT_TAG_GSUB:
+      result = _subset2<const OT::GSUB> (plan);
+      break;
+    case HB_OT_TAG_GPOS:
+      result = _subset2<const OT::GPOS> (plan);
+      break;
+
     default:
-      hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
+      hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
       if (likely (source_table))
-        result = plan->add_table(tag, source_table);
+       result = plan->add_table (tag, source_table);
       else
-        result = false;
+       result = false;
       hb_blob_destroy (source_table);
       break;
   }
-  DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED");
+  DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
   return result;
 }
 
 static bool
-_should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag)
+_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
 {
   switch (tag) {
     case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
@@ -298,10 +224,10 @@ _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag)
     case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
       return plan->drop_hints;
     // Drop Layout Tables if requested.
-    case HB_TAG ('G', 'D', 'E', 'F'): /* temporary */
-    case HB_TAG ('G', 'P', 'O', 'S'): /* temporary */
-    case HB_TAG ('G', 'S', 'U', 'B'): /* temporary */
-      return plan->drop_ot_layout;
+    case HB_OT_TAG_GDEF:
+    case HB_OT_TAG_GPOS:
+    case HB_OT_TAG_GSUB:
+      return plan->drop_layout;
     // Drop these tables below by default, list pulled
     // from fontTools:
     case HB_TAG ('B', 'A', 'S', 'E'):
@@ -330,19 +256,17 @@ _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag)
 /**
  * hb_subset:
  * @source: font face data to be subset.
- * @profile: profile to use for the subsetting.
  * @input: input to use for the subsetting.
  *
- * Subsets a font according to provided profile and input.
+ * Subsets a font according to provided input.
  **/
 hb_face_t *
 hb_subset (hb_face_t *source,
-           hb_subset_profile_t *profile,
-           hb_subset_input_t *input)
+          hb_subset_input_t *input)
 {
-  if (unlikely (!profile || !input || !source)) return hb_face_get_empty();
+  if (unlikely (!input || !source)) return hb_face_get_empty ();
 
-  hb_subset_plan_t *plan = hb_subset_plan_create (source, profile, input);
+  hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
 
   hb_tag_t table_tags[32];
   unsigned int offset = 0, count;
@@ -353,31 +277,17 @@ hb_subset (hb_face_t *source,
     for (unsigned int i = 0; i < count; i++)
     {
       hb_tag_t tag = table_tags[i];
-      if (_should_drop_table(plan, tag))
+      if (_should_drop_table (plan, tag))
       {
-        DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG(tag));
-        continue;
+       DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG (tag));
+       continue;
       }
       success = success && _subset_table (plan, tag);
     }
     offset += count;
-  } while (count == ARRAY_LENGTH (table_tags));
+  } while (success && count == ARRAY_LENGTH (table_tags));
 
-  hb_face_t *result = success ? hb_face_reference(plan->dest) : hb_face_get_empty();
+  hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
   hb_subset_plan_destroy (plan);
   return result;
 }
-
-/**
- * hb_subset_get_all_codepoints:
- * @source: font face data to load.
- * @out: set to add the all codepoints covered by font face, source.
- */
-void
-hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out)
-{
-  OT::cmap::accelerator_t cmap;
-  cmap.init (source);
-  cmap.get_all_codepoints (out);
-  cmap.fini();
-}
index f6d2ae0..f582e46 100644 (file)
 HB_BEGIN_DECLS
 
 /*
- * hb_subset_profile_t
- * Things that change based on target environment, e.g. OS.
- * Threadsafe for multiple concurrent subset operations.
- */
-
-typedef struct hb_subset_profile_t hb_subset_profile_t;
-
-HB_EXTERN hb_subset_profile_t *
-hb_subset_profile_create (void);
-
-HB_EXTERN void
-hb_subset_profile_destroy (hb_subset_profile_t *profile);
-
-/*
  * hb_subset_input_t
  *
  * Things that change based on the input. Characters to keep, etc.
@@ -68,21 +54,28 @@ hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
 HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                               hb_bool_t drop_hints);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
+
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_layout);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
 
-/* hb_subset() */
+/* hb_subset () */
 HB_EXTERN hb_face_t *
-hb_subset (hb_face_t *source,
-          hb_subset_profile_t *profile,
-           hb_subset_input_t *input);
+hb_subset (hb_face_t *source, hb_subset_input_t *input);
 
-/* hb_subset_get_all_codepoints */
-HB_EXTERN void
-hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out);
 
 HB_END_DECLS
 
diff --git a/src/hb-subset.hh b/src/hb-subset.hh
new file mode 100644 (file)
index 0000000..45cb763
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_HH
+#define HB_SUBSET_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-machinery.hh"
+#include "hb-subset-input.hh"
+#include "hb-subset-plan.hh"
+
+struct hb_subset_context_t :
+       hb_dispatch_context_t<hb_subset_context_t, bool, HB_DEBUG_SUBSET>
+{
+  const char *get_name () { return "SUBSET"; }
+  template <typename T>
+  bool dispatch (const T &obj) { return obj.subset (this); }
+  static bool default_return_value () { return true; }
+
+  hb_subset_plan_t *plan;
+  hb_serialize_context_t *serializer;
+  unsigned int debug_depth;
+
+  hb_subset_context_t (hb_subset_plan_t *plan_,
+                      hb_serialize_context_t *serializer_) :
+                       plan (plan_),
+                       serializer (serializer_),
+                       debug_depth (0) {}
+};
+
+
+#endif /* HB_SUBSET_HH */
index 2c08718..534935f 100644 (file)
@@ -14,9 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
 
 #include "ucdn.h"
 
@@ -181,15 +181,6 @@ hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED,
     return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
 }
 
-static unsigned int
-hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                       hb_codepoint_t unicode,
-                       void *user_data HB_UNUSED)
-{
-    int w = ucdn_get_east_asian_width(unicode);
-    return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1;
-}
-
 static hb_unicode_general_category_t
 hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
                         hb_codepoint_t unicode,
@@ -230,56 +221,48 @@ hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
     return ucdn_decompose(ab, a, b);
 }
 
-static unsigned int
-hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                               hb_codepoint_t u, hb_codepoint_t *decomposed,
-                               void *user_data HB_UNUSED)
-{
-    return ucdn_compat_decompose(u, decomposed);
-}
 
-static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ucdn_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr))
-    goto retry;
-
-  hb_unicode_funcs_destroy (ucdn_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ucdn_funcs ();
 #endif
 
-extern "C" HB_INTERNAL
-hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs (void)
+static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
 {
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-
-  if (unlikely (!funcs))
+  static hb_unicode_funcs_t *create ()
   {
-    funcs = hb_unicode_funcs_create (nullptr);
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
 
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr);
 
     hb_unicode_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ucdn_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ucdn_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_ucdn_funcs ()
+{
+  static_ucdn_funcs.free_instance ();
+}
 #endif
-  };
 
-  return hb_unicode_funcs_reference (funcs);
+extern "C" HB_INTERNAL
+hb_unicode_funcs_t *
+hb_ucdn_get_unicode_funcs ();
+
+hb_unicode_funcs_t *
+hb_ucdn_get_unicode_funcs ()
+{
+  return static_ucdn_funcs.get_unconst ();
 }
index 59bbf55..9529940 100644 (file)
@@ -95,8 +95,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -294,6 +293,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
index 9b0f9d4..05d46d2 100644 (file)
@@ -456,8 +456,6 @@ int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed);
  */
 int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b);
 
-#ifdef __cplusplus
-}
-#endif
+HB_END_HEADER
 
 #endif
diff --git a/src/hb-unicode-emoji-table.hh b/src/hb-unicode-emoji-table.hh
new file mode 100644 (file)
index 0000000..1dd0b32
--- /dev/null
@@ -0,0 +1,110 @@
+/* == Start of generated table == */
+/*
+ * The following tables are generated by running:
+ *
+ *   ./gen-emoji-table.py emoji-data.txt
+ *
+ * on file with this header:
+ *
+ * # emoji-data.txt
+ * # Date: 2018-02-07, 07:55:18 GMT
+ * # © 2018 Unicode®, Inc.
+ * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+ * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * #
+ * # Emoji Data for UTS #51
+ * # Version: 11.0
+ * #
+ * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ */
+
+#ifndef HB_UNICODE_EMOJI_TABLE_HH
+#define HB_UNICODE_EMOJI_TABLE_HH
+
+#include "hb-unicode.hh"
+
+
+static const struct hb_unicode_range_t _hb_unicode_emoji_Extended_Pictographic_table[] =
+{
+  {0x00A9, 0x00A9},
+  {0x00AE, 0x00AE},
+  {0x203C, 0x203C},
+  {0x2049, 0x2049},
+  {0x2122, 0x2122},
+  {0x2139, 0x2139},
+  {0x2194, 0x2199},
+  {0x21A9, 0x21AA},
+  {0x231A, 0x231B},
+  {0x2328, 0x2328},
+  {0x2388, 0x2388},
+  {0x23CF, 0x23CF},
+  {0x23E9, 0x23F3},
+  {0x23F8, 0x23FA},
+  {0x24C2, 0x24C2},
+  {0x25AA, 0x25AB},
+  {0x25B6, 0x25B6},
+  {0x25C0, 0x25C0},
+  {0x25FB, 0x25FE},
+  {0x2600, 0x2605},
+  {0x2607, 0x2612},
+  {0x2614, 0x2685},
+  {0x2690, 0x2705},
+  {0x2708, 0x2712},
+  {0x2714, 0x2714},
+  {0x2716, 0x2716},
+  {0x271D, 0x271D},
+  {0x2721, 0x2721},
+  {0x2728, 0x2728},
+  {0x2733, 0x2734},
+  {0x2744, 0x2744},
+  {0x2747, 0x2747},
+  {0x274C, 0x274C},
+  {0x274E, 0x274E},
+  {0x2753, 0x2755},
+  {0x2757, 0x2757},
+  {0x2763, 0x2767},
+  {0x2795, 0x2797},
+  {0x27A1, 0x27A1},
+  {0x27B0, 0x27B0},
+  {0x27BF, 0x27BF},
+  {0x2934, 0x2935},
+  {0x2B05, 0x2B07},
+  {0x2B1B, 0x2B1C},
+  {0x2B50, 0x2B50},
+  {0x2B55, 0x2B55},
+  {0x3030, 0x3030},
+  {0x303D, 0x303D},
+  {0x3297, 0x3297},
+  {0x3299, 0x3299},
+  {0x1F000, 0x1F0FF},
+  {0x1F10D, 0x1F10F},
+  {0x1F12F, 0x1F12F},
+  {0x1F16C, 0x1F171},
+  {0x1F17E, 0x1F17F},
+  {0x1F18E, 0x1F18E},
+  {0x1F191, 0x1F19A},
+  {0x1F1AD, 0x1F1E5},
+  {0x1F201, 0x1F20F},
+  {0x1F21A, 0x1F21A},
+  {0x1F22F, 0x1F22F},
+  {0x1F232, 0x1F23A},
+  {0x1F23C, 0x1F23F},
+  {0x1F249, 0x1F3FA},
+  {0x1F400, 0x1F53D},
+  {0x1F546, 0x1F64F},
+  {0x1F680, 0x1F6FF},
+  {0x1F774, 0x1F77F},
+  {0x1F7D5, 0x1F7FF},
+  {0x1F80C, 0x1F80F},
+  {0x1F848, 0x1F84F},
+  {0x1F85A, 0x1F85F},
+  {0x1F888, 0x1F88F},
+  {0x1F8AE, 0x1F8FF},
+  {0x1F90C, 0x1F93A},
+  {0x1F93C, 0x1F945},
+  {0x1F947, 0x1FFFD},
+};
+
+#endif /* HB_UNICODE_EMOJI_TABLE_HH */
+
+/* == End of generated table == */
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
deleted file mode 100644 (file)
index 5472ece..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2010,2011,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
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UNICODE_PRIVATE_HH
-#define HB_UNICODE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
-
-/*
- * hb_unicode_funcs_t
- */
-
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (script) \
-  HB_UNICODE_FUNC_IMPLEMENT (compose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
-  /* ^--- Add new callbacks here */
-
-/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
-  /* ^--- Add new simple callbacks here */
-
-struct hb_unicode_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_unicode_funcs_t *parent;
-
-  bool immutable;
-
-#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
-  inline return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-  inline hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
-                           hb_codepoint_t *ab)
-  {
-    *ab = 0;
-    if (unlikely (!a || !b)) return false;
-    return func.compose (this, a, b, ab, user_data.compose);
-  }
-
-  inline hb_bool_t decompose (hb_codepoint_t ab,
-                             hb_codepoint_t *a, hb_codepoint_t *b)
-  {
-    *a = ab; *b = 0;
-    return func.decompose (this, ab, a, b, user_data.decompose);
-  }
-
-  inline unsigned int decompose_compatibility (hb_codepoint_t  u,
-                                              hb_codepoint_t *decomposed)
-  {
-    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
-    if (ret == 1 && u == decomposed[0]) {
-      decomposed[0] = 0;
-      return 0;
-    }
-    decomposed[ret] = 0;
-    return ret;
-  }
-
-
-  inline unsigned int
-  modified_combining_class (hb_codepoint_t unicode)
-  {
-    /* XXX This hack belongs to the Myanmar shaper. */
-    if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
-
-    /* XXX This hack belongs to the USE shaper (for Tai Tham):
-     * Reorder SAKOT to ensure it comes after any tone marks. */
-    if (unlikely (unicode == 0x1A60u)) return 254;
-
-    /* XXX This hack belongs to the Tibetan shaper:
-     * Reorder PADMA to ensure it comes after any vowel marks. */
-    if (unlikely (unicode == 0x0FC6u)) return 254;
-    /* Reorder TSA -PHRU to reorder before U+0F74 */
-    if (unlikely (unicode == 0x0F39u)) return 127;
-
-    return _hb_modified_combining_class[combining_class (unicode)];
-  }
-
-  static inline hb_bool_t
-  is_variation_selector (hb_codepoint_t unicode)
-  {
-    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
-     * Arabic shaper.  No need to match them here. */
-    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
-                                  0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
-                                  0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
-  }
-
-  /* Default_Ignorable codepoints:
-   *
-   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
-   * we do NOT want to hide them, as the way Uniscribe has implemented them
-   * is with regular spacing glyphs, and that's the way fonts are made to work.
-   * As such, we make exceptions for those four.
-   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
-   *
-   * Unicode 7.0:
-   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
-   * 00AD          # Cf       SOFT HYPHEN
-   * 034F          # Mn       COMBINING GRAPHEME JOINER
-   * 061C          # Cf       ARABIC LETTER MARK
-   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
-   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
-   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
-   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
-   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
-   * 2065          # Cn       <reserved-2065>
-   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
-   * 3164          # Lo       HANGUL FILLER
-   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
-   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
-   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
-   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
-   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
-   * E0000         # Cn       <reserved-E0000>
-   * E0001         # Cf       LANGUAGE TAG
-   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
-   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
-   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
-   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
-   */
-  static inline hb_bool_t
-  is_default_ignorable (hb_codepoint_t ch)
-  {
-    hb_codepoint_t plane = ch >> 16;
-    if (likely (plane == 0))
-    {
-      /* BMP */
-      hb_codepoint_t page = ch >> 8;
-      switch (page) {
-       case 0x00: return unlikely (ch == 0x00ADu);
-       case 0x03: return unlikely (ch == 0x034Fu);
-       case 0x06: return unlikely (ch == 0x061Cu);
-       case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
-       case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
-       case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
-                                           0x202Au, 0x202Eu,
-                                           0x2060u, 0x206Fu);
-       case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
-       case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
-       default: return false;
-      }
-    }
-    else
-    {
-      /* Other planes */
-      switch (plane) {
-       case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
-       case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
-       default: return false;
-      }
-    }
-  }
-
-  /* Space estimates based on:
-   * https://unicode.org/charts/PDF/U2000.pdf
-   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
-   */
-  enum space_t {
-    NOT_SPACE = 0,
-    SPACE_EM   = 1,
-    SPACE_EM_2 = 2,
-    SPACE_EM_3 = 3,
-    SPACE_EM_4 = 4,
-    SPACE_EM_5 = 5,
-    SPACE_EM_6 = 6,
-    SPACE_EM_16 = 16,
-    SPACE_4_EM_18,     /* 4/18th of an EM! */
-    SPACE,
-    SPACE_FIGURE,
-    SPACE_PUNCTUATION,
-    SPACE_NARROW,
-  };
-  static inline space_t
-  space_fallback_type (hb_codepoint_t u)
-  {
-    switch (u)
-    {
-      /* All GC=Zs chars that can use a fallback. */
-      default:     return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
-      case 0x0020u: return SPACE;      /* U+0020 SPACE */
-      case 0x00A0u: return SPACE;      /* U+00A0 NO-BREAK SPACE */
-      case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */
-      case 0x2001u: return SPACE_EM;   /* U+2001 EM QUAD */
-      case 0x2002u: return SPACE_EM_2; /* U+2002 EN SPACE */
-      case 0x2003u: return SPACE_EM;   /* U+2003 EM SPACE */
-      case 0x2004u: return SPACE_EM_3; /* U+2004 THREE-PER-EM SPACE */
-      case 0x2005u: return SPACE_EM_4; /* U+2005 FOUR-PER-EM SPACE */
-      case 0x2006u: return SPACE_EM_6; /* U+2006 SIX-PER-EM SPACE */
-      case 0x2007u: return SPACE_FIGURE;       /* U+2007 FIGURE SPACE */
-      case 0x2008u: return SPACE_PUNCTUATION;  /* U+2008 PUNCTUATION SPACE */
-      case 0x2009u: return SPACE_EM_5;         /* U+2009 THIN SPACE */
-      case 0x200Au: return SPACE_EM_16;                /* U+200A HAIR SPACE */
-      case 0x202Fu: return SPACE_NARROW;       /* U+202F NARROW NO-BREAK SPACE */
-      case 0x205Fu: return SPACE_4_EM_18;      /* U+205F MEDIUM MATHEMATICAL SPACE */
-      case 0x3000u: return SPACE_EM;           /* U+3000 IDEOGRAPHIC SPACE */
-    }
-  }
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } func;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } destroy;
-};
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
-
-
-/* Modified combining marks */
-
-/* Hebrew
- *
- * We permute the "fixed-position" classes 10-26 into the order
- * described in the SBL Hebrew manual:
- *
- * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
- *
- * (as recommended by:
- *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
- *
- * More details here:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
-#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
-#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
-#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
-#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
-#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
-#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
-#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
-#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
-
-/*
- * Arabic
- *
- * Modify to move Shadda (ccc=33) before other marks.  See:
- * https://unicode.org/faq/normalization.html#8
- * https://unicode.org/faq/normalization.html#9
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
-#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
-#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
-#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
-#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
-#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
-
-/* Syriac */
-#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
-
-/* Telugu
- *
- * Modify Telugu length marks (ccc=84, ccc=91).
- * These are the only matras in the main Indic scripts range that have
- * a non-zero ccc.  That makes them reorder with the Halant that is
- * ccc=9.  Just zero them, we don't need them in our Indic shaper.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
-#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
-
-/* Thai
- *
- * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
- * Assign 3, which is unassigned otherwise.
- * Uniscribe does this reordering too.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
-
-/* Lao */
-#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
-
-/* Tibetan
- *
- * In case of multiple vowel-signs, use u first (but after achung)
- * this allows Dzongkha multi-vowel shortcuts to render correctly
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
-#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
-#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
-
-/* Misc */
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
-       (FLAG_UNSAFE (gen_cat) & \
-        (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \
-       (FLAG_UNSAFE (gen_cat) & \
-        (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-         FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
-
-#endif /* HB_UNICODE_PRIVATE_HH */
index 2d16c2e..4ac521d 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-unicode-private.hh"
+#include "hb-unicode.hh"
 
 
+/**
+ * SECTION: hb-unicode
+ * @title: hb-unicode
+ * @short_description: Unicode character property access
+ * @include: hb.h
+ *
+ * Unicode functions are used to access Unicode character properties.
+ * Client can pass its own Unicode functions to HarfBuzz, or access
+ * the built-in Unicode functions that come with HarfBuzz.
+ *
+ * With the Unicode functions, one can query variour Unicode character
+ * properties, such as General Category, Script, Combining Class, etc.
+ **/
+
 
 /*
  * hb_unicode_funcs_t
@@ -109,40 +123,23 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs     HB_UNUSED
 }
 
 
-#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
-  HB_UNICODE_FUNCS_IMPLEMENT (glib) \
-  HB_UNICODE_FUNCS_IMPLEMENT (icu) \
-  HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
-  HB_UNICODE_FUNCS_IMPLEMENT (nil) \
-  /* ^--- Add new callbacks before nil */
-
-#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
-
-/* Prototype them all */
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
-HB_UNICODE_FUNCS_IMPLEMENT_SET
-#undef HB_UNICODE_FUNCS_IMPLEMENT
-
+extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs ();
 
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_default (void)
+hb_unicode_funcs_get_default ()
 {
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-  return hb_##set##_get_unicode_funcs ();
-
 #if defined(HAVE_UCDN)
-  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
+  return hb_ucdn_get_unicode_funcs ();
 #elif defined(HAVE_GLIB)
-  HB_UNICODE_FUNCS_IMPLEMENT(glib)
+  return hb_glib_get_unicode_funcs ();
 #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-  HB_UNICODE_FUNCS_IMPLEMENT(icu)
+  return hb_icu_get_unicode_funcs ();
 #else
 #define HB_UNICODE_FUNCS_NIL 1
-  HB_UNICODE_FUNCS_IMPLEMENT(nil)
+  return hb_unicode_funcs_get_empty ();
 #endif
-
-#undef HB_UNICODE_FUNCS_IMPLEMENT
 }
 
 #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
@@ -154,7 +151,7 @@ hb_unicode_funcs_get_default (void)
  * hb_unicode_funcs_create: (Xconstructor)
  * @parent: (nullable):
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -185,11 +182,11 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
 }
 
 
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   nullptr, /* parent */
-  true, /* immutable */
   {
 #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
     HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
@@ -200,23 +197,23 @@ const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
 /**
  * hb_unicode_funcs_get_empty:
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
  * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_empty (void)
+hb_unicode_funcs_get_empty ()
 {
-  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
+  return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
 }
 
 /**
  * hb_unicode_funcs_reference: (skip)
  * @ufuncs: Unicode functions.
  *
- * 
+ *
  *
  * Return value: (transfer full):
  *
@@ -232,7 +229,7 @@ hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
  * hb_unicode_funcs_destroy: (skip)
  * @ufuncs: Unicode functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -254,14 +251,14 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
 /**
  * hb_unicode_funcs_set_user_data: (skip)
  * @ufuncs: Unicode functions.
- * @key: 
- * @data: 
- * @destroy: 
- * @replace: 
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
+ *
  *
- * 
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -278,9 +275,9 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
 /**
  * hb_unicode_funcs_get_user_data: (skip)
  * @ufuncs: Unicode functions.
- * @key: 
+ * @key:
+ *
  *
- * 
  *
  * Return value: (transfer none):
  *
@@ -298,42 +295,42 @@ hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
  * hb_unicode_funcs_make_immutable:
  * @ufuncs: Unicode functions.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
 void
 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  if (unlikely (hb_object_is_inert (ufuncs)))
+  if (hb_object_is_immutable (ufuncs))
     return;
 
-  ufuncs->immutable = true;
+  hb_object_make_immutable (ufuncs);
 }
 
 /**
  * hb_unicode_funcs_is_immutable:
  * @ufuncs: Unicode functions.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
 hb_bool_t
 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  return ufuncs->immutable;
+  return hb_object_is_immutable (ufuncs);
 }
 
 /**
  * hb_unicode_funcs_get_parent:
  * @ufuncs: Unicode functions.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -352,7 +349,7 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t                 *ufuncs,     \
                                    void                           *user_data,  \
                                    hb_destroy_func_t               destroy)    \
 {                                                                              \
-  if (ufuncs->immutable)                                                       \
+  if (hb_object_is_immutable (ufuncs))                                         \
     return;                                                                    \
                                                                                \
   if (ufuncs->destroy.name)                                                    \
@@ -387,13 +384,13 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
 /**
  * hb_unicode_compose:
  * @ufuncs: Unicode functions.
- * @a: 
- * @b: 
+ * @a:
+ * @b:
  * @ab: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -409,13 +406,13 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
 /**
  * hb_unicode_decompose:
  * @ufuncs: Unicode functions.
- * @ab: 
+ * @ab:
  * @a: (out):
  * @b: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -431,14 +428,15 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
 /**
  * hb_unicode_decompose_compatibility:
  * @ufuncs: Unicode functions.
- * @u: 
+ * @u:
  * @decomposed: (out):
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 unsigned int
 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
@@ -449,7 +447,7 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
 }
 
 
-/* See hb-unicode-private.hh for details. */
+/* See hb-unicode.hh for details. */
 const uint8_t
 _hb_modified_combining_class[256] =
 {
@@ -561,3 +559,19 @@ _hb_modified_combining_class[256] =
   241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
   255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
 };
+
+
+/*
+ * Emoji
+ */
+
+#include "hb-unicode-emoji-table.hh"
+
+bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp)
+{
+  return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table,
+                    ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table),
+                    sizeof (hb_unicode_range_t),
+                    hb_unicode_range_t::cmp);
+}
index 2657f48..df0b91f 100644 (file)
 HB_BEGIN_DECLS
 
 
+/**
+ * HB_UNICODE_MAX
+ *
+ * Since: 1.9.0
+ **/
+#define HB_UNICODE_MAX 0x10FFFFu
+
+
 /* hb_unicode_general_category_t */
 
 /* Unicode Character Database property: General_Category (gc) */
@@ -222,9 +230,6 @@ hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
 typedef hb_unicode_combining_class_t   (*hb_unicode_combining_class_func_t)    (hb_unicode_funcs_t *ufuncs,
                                                                                 hb_codepoint_t      unicode,
                                                                                 void               *user_data);
-typedef unsigned int                   (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                hb_codepoint_t      unicode,
-                                                                                void               *user_data);
 typedef hb_unicode_general_category_t  (*hb_unicode_general_category_func_t)   (hb_unicode_funcs_t *ufuncs,
                                                                                 hb_codepoint_t      unicode,
                                                                                 void               *user_data);
@@ -246,32 +251,6 @@ typedef hb_bool_t                  (*hb_unicode_decompose_func_t)          (hb_unicode_funcs_t *ufuncs,
                                                                                 hb_codepoint_t     *b,
                                                                                 void               *user_data);
 
-/**
- * hb_unicode_decompose_compatibility_func_t:
- * @ufuncs: a Unicode function structure
- * @u: codepoint to decompose
- * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
- * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
- *
- * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
- * The complete length of the decomposition will be returned.
- *
- * If @u has no compatibility decomposition, zero should be returned.
- *
- * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
- * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
- * of this function type must ensure that they do not write past the provided array.
- *
- * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
- */
-typedef unsigned int                   (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                        hb_codepoint_t      u,
-                                                                                        hb_codepoint_t     *decomposed,
-                                                                                        void               *user_data);
-
-/* See Unicode 6.1 for details on the maximum decomposition length. */
-#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
-
 /* setters */
 
 /**
@@ -291,22 +270,6 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
                                           void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_unicode_funcs_set_eastasian_width_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
-                                          hb_unicode_eastasian_width_func_t func,
-                                          void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_unicode_funcs_set_general_category_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -386,22 +349,6 @@ hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
                                     hb_unicode_decompose_func_t func,
                                     void *user_data, hb_destroy_func_t destroy);
 
-/**
- * hb_unicode_funcs_set_decompose_compatibility_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- * 
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
-                                                  hb_unicode_decompose_compatibility_func_t func,
-                                                  void *user_data, hb_destroy_func_t destroy);
-
 /* accessors */
 
 /**
@@ -414,15 +361,6 @@ hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
                            hb_codepoint_t unicode);
 
 /**
- * hb_unicode_eastasian_width:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN unsigned int
-hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
-                           hb_codepoint_t unicode);
-
-/**
  * hb_unicode_general_category:
  *
  * Since: 0.9.2
@@ -461,11 +399,6 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
                      hb_codepoint_t     *a,
                      hb_codepoint_t     *b);
 
-HB_EXTERN unsigned int
-hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
-                                   hb_codepoint_t      u,
-                                   hb_codepoint_t     *decomposed);
-
 HB_END_DECLS
 
 #endif /* HB_UNICODE_H */
diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh
new file mode 100644 (file)
index 0000000..82ebb10
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  Codethink Limited
+ * Copyright © 2010,2011,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
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UNICODE_HH
+#define HB_UNICODE_HH
+
+#include "hb.hh"
+
+
+extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
+
+/*
+ * hb_unicode_funcs_t
+ */
+
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (script) \
+  HB_UNICODE_FUNC_IMPLEMENT (compose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
+  /* ^--- Add new callbacks here */
+
+/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
+  /* ^--- Add new simple callbacks here */
+
+struct hb_unicode_funcs_t
+{
+  hb_object_header_t header;
+
+  hb_unicode_funcs_t *parent;
+
+#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
+  return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
+HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+  hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
+                    hb_codepoint_t *ab)
+  {
+    *ab = 0;
+    if (unlikely (!a || !b)) return false;
+    return func.compose (this, a, b, ab, user_data.compose);
+  }
+
+  hb_bool_t decompose (hb_codepoint_t ab,
+                      hb_codepoint_t *a, hb_codepoint_t *b)
+  {
+    *a = ab; *b = 0;
+    return func.decompose (this, ab, a, b, user_data.decompose);
+  }
+
+  unsigned int decompose_compatibility (hb_codepoint_t  u,
+                                       hb_codepoint_t *decomposed)
+  {
+    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
+    if (ret == 1 && u == decomposed[0]) {
+      decomposed[0] = 0;
+      return 0;
+    }
+    decomposed[ret] = 0;
+    return ret;
+  }
+
+  unsigned int
+  modified_combining_class (hb_codepoint_t u)
+  {
+    /* XXX This hack belongs to the Myanmar shaper. */
+    if (unlikely (u == 0x1037u)) u = 0x103Au;
+
+    /* XXX This hack belongs to the USE shaper (for Tai Tham):
+     * Reorder SAKOT to ensure it comes after any tone marks. */
+    if (unlikely (u == 0x1A60u)) return 254;
+
+    /* XXX This hack belongs to the Tibetan shaper:
+     * Reorder PADMA to ensure it comes after any vowel marks. */
+    if (unlikely (u == 0x0FC6u)) return 254;
+    /* Reorder TSA -PHRU to reorder before U+0F74 */
+    if (unlikely (u == 0x0F39u)) return 127;
+
+    return _hb_modified_combining_class[combining_class (u)];
+  }
+
+  static hb_bool_t
+  is_variation_selector (hb_codepoint_t unicode)
+  {
+    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+     * Arabic shaper.  No need to match them here. */
+    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
+                                                  0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
+                                                  0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
+  }
+
+  /* Default_Ignorable codepoints:
+   *
+   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
+   * we do NOT want to hide them, as the way Uniscribe has implemented them
+   * is with regular spacing glyphs, and that's the way fonts are made to work.
+   * As such, we make exceptions for those four.
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
+   *
+   * Unicode 7.0:
+   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
+   * 00AD          # Cf       SOFT HYPHEN
+   * 034F          # Mn       COMBINING GRAPHEME JOINER
+   * 061C          # Cf       ARABIC LETTER MARK
+   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
+   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
+   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
+   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
+   * 2065          # Cn       <reserved-2065>
+   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+   * 3164          # Lo       HANGUL FILLER
+   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
+   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
+   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
+   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+   * E0000         # Cn       <reserved-E0000>
+   * E0001         # Cf       LANGUAGE TAG
+   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
+   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
+   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
+   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
+   */
+  static hb_bool_t
+  is_default_ignorable (hb_codepoint_t ch)
+  {
+    hb_codepoint_t plane = ch >> 16;
+    if (likely (plane == 0))
+    {
+      /* BMP */
+      hb_codepoint_t page = ch >> 8;
+      switch (page) {
+       case 0x00: return unlikely (ch == 0x00ADu);
+       case 0x03: return unlikely (ch == 0x034Fu);
+       case 0x06: return unlikely (ch == 0x061Cu);
+       case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
+       case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
+       case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
+                                           0x202Au, 0x202Eu,
+                                           0x2060u, 0x206Fu);
+       case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
+       case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
+       default: return false;
+      }
+    }
+    else
+    {
+      /* Other planes */
+      switch (plane) {
+       case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
+       case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
+       default: return false;
+      }
+    }
+  }
+
+  /* Space estimates based on:
+   * https://unicode.org/charts/PDF/U2000.pdf
+   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
+   */
+  enum space_t {
+    NOT_SPACE = 0,
+    SPACE_EM   = 1,
+    SPACE_EM_2 = 2,
+    SPACE_EM_3 = 3,
+    SPACE_EM_4 = 4,
+    SPACE_EM_5 = 5,
+    SPACE_EM_6 = 6,
+    SPACE_EM_16 = 16,
+    SPACE_4_EM_18,     /* 4/18th of an EM! */
+    SPACE,
+    SPACE_FIGURE,
+    SPACE_PUNCTUATION,
+    SPACE_NARROW,
+  };
+  static space_t
+  space_fallback_type (hb_codepoint_t u)
+  {
+    switch (u)
+    {
+      /* All GC=Zs chars that can use a fallback. */
+      default:     return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
+      case 0x0020u: return SPACE;      /* U+0020 SPACE */
+      case 0x00A0u: return SPACE;      /* U+00A0 NO-BREAK SPACE */
+      case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */
+      case 0x2001u: return SPACE_EM;   /* U+2001 EM QUAD */
+      case 0x2002u: return SPACE_EM_2; /* U+2002 EN SPACE */
+      case 0x2003u: return SPACE_EM;   /* U+2003 EM SPACE */
+      case 0x2004u: return SPACE_EM_3; /* U+2004 THREE-PER-EM SPACE */
+      case 0x2005u: return SPACE_EM_4; /* U+2005 FOUR-PER-EM SPACE */
+      case 0x2006u: return SPACE_EM_6; /* U+2006 SIX-PER-EM SPACE */
+      case 0x2007u: return SPACE_FIGURE;       /* U+2007 FIGURE SPACE */
+      case 0x2008u: return SPACE_PUNCTUATION;  /* U+2008 PUNCTUATION SPACE */
+      case 0x2009u: return SPACE_EM_5;         /* U+2009 THIN SPACE */
+      case 0x200Au: return SPACE_EM_16;                /* U+200A HAIR SPACE */
+      case 0x202Fu: return SPACE_NARROW;       /* U+202F NARROW NO-BREAK SPACE */
+      case 0x205Fu: return SPACE_4_EM_18;      /* U+205F MEDIUM MATHEMATICAL SPACE */
+      case 0x3000u: return SPACE_EM;           /* U+3000 IDEOGRAPHIC SPACE */
+    }
+  }
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } func;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } destroy;
+};
+DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
+
+
+/*
+ * Modified combining marks
+ */
+
+/* Hebrew
+ *
+ * We permute the "fixed-position" classes 10-26 into the order
+ * described in the SBL Hebrew manual:
+ *
+ * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
+ *
+ * (as recommended by:
+ *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
+ *
+ * More details here:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
+#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
+#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
+#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
+#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
+#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
+#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
+#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
+#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
+
+/*
+ * Arabic
+ *
+ * Modify to move Shadda (ccc=33) before other marks.  See:
+ * https://unicode.org/faq/normalization.html#8
+ * https://unicode.org/faq/normalization.html#9
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
+#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
+#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
+#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
+#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
+#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
+
+/* Syriac */
+#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
+
+/* Telugu
+ *
+ * Modify Telugu length marks (ccc=84, ccc=91).
+ * These are the only matras in the main Indic scripts range that have
+ * a non-zero ccc.  That makes them reorder with the Halant that is
+ * ccc=9.  Just zero them, we don't need them in our Indic shaper.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
+#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
+
+/* Thai
+ *
+ * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
+ * Assign 3, which is unassigned otherwise.
+ * Uniscribe does this reordering too.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
+
+/* Lao */
+#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
+
+/* Tibetan
+ *
+ * In case of multiple vowel-signs, use u first (but after achung)
+ * this allows Dzongkha multi-vowel shortcuts to render correctly
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
+#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
+#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
+
+/* Misc */
+
+#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
+       (FLAG_UNSAFE (gen_cat) & \
+        (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
+         FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
+         FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
+
+
+/*
+ * Ranges, used for bsearch tables.
+ */
+
+struct hb_unicode_range_t
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const hb_unicode_range_t *range = (hb_unicode_range_t *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
+  hb_codepoint_t start;
+  hb_codepoint_t end;
+};
+
+/*
+ * Emoji.
+ */
+
+HB_INTERNAL bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp);
+
+
+#endif /* HB_UNICODE_HH */
index 6d6afe8..31c50df 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#define HB_SHAPER uniscribe
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
 
 #include <windows.h>
 #include <usp10.h>
 
 #include "hb-uniscribe.h"
 
-#include "hb-open-file-private.hh"
+#include "hb-open-file.hh"
 #include "hb-ot-name-table.hh"
-#include "hb-ot-tag.h"
+#include "hb-ot-layout.h"
+
+
+/**
+ * SECTION:hb-uniscribe
+ * @title: hb-uniscribe
+ * @short_description: Windows integration
+ * @include: hb-uniscribe.h
+ *
+ * Functions for using HarfBuzz with the Windows fonts.
+ **/
 
 
 static inline uint16_t hb_uint16_swap (const uint16_t v)
@@ -191,12 +199,13 @@ hb_ScriptPlaceOpenType(
 }
 
 
-struct hb_uniscribe_shaper_funcs_t {
+struct hb_uniscribe_shaper_funcs_t
+{
   SIOT ScriptItemizeOpenType;
   SSOT ScriptShapeOpenType;
   SPOT ScriptPlaceOpenType;
 
-  inline void init (void)
+  void init ()
   {
     HMODULE hinstLib;
     this->ScriptItemizeOpenType = nullptr;
@@ -206,9 +215,12 @@ struct hb_uniscribe_shaper_funcs_t {
     hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
     if (hinstLib)
     {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
       this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
       this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
       this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
+#pragma GCC diagnostic pop
     }
     if (!this->ScriptItemizeOpenType ||
        !this->ScriptShapeOpenType   ||
@@ -221,47 +233,49 @@ struct hb_uniscribe_shaper_funcs_t {
     }
   }
 };
-static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
 
-#ifdef HB_USE_ATEXIT
-static inline void
-free_uniscribe_funcs (void)
-{
-retry:
-  hb_uniscribe_shaper_funcs_t *local_uniscribe_funcs =
-    (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
-  if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, local_uniscribe_funcs, nullptr))
-    goto retry;
 
-  free (uniscribe_funcs);
-}
-#endif
+static void free_static_uniscribe_shaper_funcs ();
 
-static hb_uniscribe_shaper_funcs_t *
-hb_uniscribe_shaper_get_funcs (void)
+static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
+                                                                        hb_uniscribe_shaper_funcs_lazy_loader_t>
 {
-retry:
-  hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
-
-  if (unlikely (!funcs))
+  static hb_uniscribe_shaper_funcs_t *create ()
   {
-    funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
+    hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
     if (unlikely (!funcs))
       return nullptr;
 
     funcs->init ();
 
-    if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, nullptr, funcs)) {
-      free (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+    atexit (free_static_uniscribe_shaper_funcs);
 #endif
+
+    return funcs;
   }
+  static void destroy (hb_uniscribe_shaper_funcs_t *p)
+  {
+    free ((void *) p);
+  }
+  static hb_uniscribe_shaper_funcs_t *get_null ()
+  {
+    return nullptr;
+  }
+} static_uniscribe_shaper_funcs;
+
+#if HB_USE_ATEXIT
+static
+void free_static_uniscribe_shaper_funcs ()
+{
+  static_uniscribe_shaper_funcs.free_instance ();
+}
+#endif
 
-  return funcs;
+static hb_uniscribe_shaper_funcs_t *
+hb_uniscribe_shaper_get_funcs ()
+{
+  return static_uniscribe_shaper_funcs.get_unconst ();
 }
 
 
@@ -277,9 +291,8 @@ struct active_feature_t {
           a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
           0;
   }
-  bool operator== (const active_feature_t *f) {
-    return cmp (this, f) == 0;
-  }
+  bool operator== (const active_feature_t *f)
+  { return cmp (this, f) == 0; }
 };
 
 struct feature_event_t {
@@ -287,7 +300,8 @@ struct feature_event_t {
   bool start;
   active_feature_t feature;
 
-  static int cmp (const void *pa, const void *pb) {
+  static int cmp (const void *pa, const void *pb)
+  {
     const feature_event_t *a = (const feature_event_t *) pa;
     const feature_event_t *b = (const feature_event_t *) pb;
     return a->index < b->index ? -1 : a->index > b->index ? 1 :
@@ -302,15 +316,12 @@ struct range_record_t {
   unsigned int index_last;  /* == end - 1 */
 };
 
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
-
 
 /*
  * shaper face data
  */
 
-struct hb_uniscribe_shaper_face_data_t {
+struct hb_uniscribe_face_data_t {
   HANDLE fh;
   hb_uniscribe_shaper_funcs_t *funcs;
   wchar_t face_name[LF_FACESIZE];
@@ -359,7 +370,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
    * full, PS. All of them point to the same name data with our unique name.
    */
 
-  blob = OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (blob);
+  blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (blob);
 
   unsigned int length, new_length, name_str_len;
   const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
@@ -384,13 +395,13 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
 
   memcpy(new_sfnt_data, orig_sfnt_data, length);
 
-  OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
+  OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
   name.format.set (0);
   name.count.set (ARRAY_LENGTH (name_IDs));
   name.stringOffset.set (name.get_size ());
   for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
   {
-    OT::NameRecord &record = name.nameRecord[i];
+    OT::NameRecord &record = name.nameRecordZ[i];
     record.platformID.set (3);
     record.encodingID.set (1);
     record.languageID.set (0x0409u); /* English */
@@ -400,7 +411,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
   }
 
   /* Copy string data from new_name, converting wchar_t to UTF16BE. */
-  unsigned char *p = &OT::StructAfter<unsigned char> (name);
+  unsigned char *p = &StructAfter<unsigned char> (name);
   for (unsigned int i = 0; i < name_str_len; i++)
   {
     *p++ = new_name[i] >> 8;
@@ -440,10 +451,10 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
                         HB_MEMORY_MODE_WRITABLE, nullptr, free);
 }
 
-hb_uniscribe_shaper_face_data_t *
+hb_uniscribe_face_data_t *
 _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
 {
-  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
+  hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
   if (unlikely (!data))
     return nullptr;
 
@@ -480,7 +491,7 @@ _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
 }
 
 void
-_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
+_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_face_data_t *data)
 {
   RemoveFontMemResourceEx (data->fh);
   free (data);
@@ -491,11 +502,12 @@ _hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
  * shaper font data
  */
 
-struct hb_uniscribe_shaper_font_data_t {
+struct hb_uniscribe_font_data_t
+{
   HDC hdc;
-  LOGFONTW log_font;
+  mutable LOGFONTW log_font;
   HFONT hfont;
-  SCRIPT_CACHE script_cache;
+  mutable SCRIPT_CACHE script_cache;
   double x_mult, y_mult; /* From LOGFONT space to HB space. */
 };
 
@@ -508,20 +520,15 @@ populate_log_font (LOGFONTW  *lf,
   lf->lfHeight = - (int) font_size;
   lf->lfCharSet = DEFAULT_CHARSET;
 
-  hb_face_t *face = font->face;
-  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-
-  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
+  memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
 
   return true;
 }
 
-hb_uniscribe_shaper_font_data_t *
+hb_uniscribe_font_data_t *
 _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
-
-  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
+  hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
   if (unlikely (!data))
     return nullptr;
 
@@ -560,7 +567,7 @@ _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
 }
 
 void
-_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
+_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_font_data_t *data)
 {
   if (data->hdc)
     ReleaseDC (nullptr, data->hdc);
@@ -574,39 +581,15 @@ _hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
 LOGFONTW *
 hb_uniscribe_font_get_logfontw (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
-  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
-  return &font_data->log_font;
+  const hb_uniscribe_font_data_t *data =  font->data.uniscribe;
+  return data ? &data->log_font : nullptr;
 }
 
 HFONT
 hb_uniscribe_font_get_hfont (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
-  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
-  return font_data->hfont;
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_uniscribe_shaper_shape_plan_data_t {};
-
-hb_uniscribe_shaper_shape_plan_data_t *
-_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
-{
+  const hb_uniscribe_font_data_t *data =  font->data.uniscribe;
+  return data ? data->hfont : nullptr;
 }
 
 
@@ -623,19 +606,19 @@ _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+  const hb_uniscribe_face_data_t *face_data = face->data.uniscribe;
+  const hb_uniscribe_font_data_t *font_data = font->data.uniscribe;
   hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
 
   /*
    * Set up features.
    */
-  hb_auto_t<hb_vector_t<OPENTYPE_FEATURE_RECORD> > feature_records;
-  hb_auto_t<hb_vector_t<range_record_t> > range_records;
+  hb_vector_t<OPENTYPE_FEATURE_RECORD> feature_records;
+  hb_vector_t<range_record_t> range_records;
   if (num_features)
   {
     /* Sort features by start/end events. */
-    hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
+    hb_vector_t<feature_event_t> feature_events;
     for (unsigned int i = 0; i < num_features; i++)
     {
       active_feature_t feature;
@@ -670,9 +653,9 @@ _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
     }
 
     /* Scan events and save features for each range. */
-    hb_auto_t<hb_vector_t<active_feature_t> > active_features;
+    hb_vector_t<active_feature_t> active_features;
     unsigned int last_index = 0;
-    for (unsigned int i = 0; i < feature_events.len; i++)
+    for (unsigned int i = 0; i < feature_events.length; i++)
     {
       feature_event_t *event = &feature_events[i];
 
@@ -681,26 +664,26 @@ _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
         /* Save a snapshot of active features and the range. */
        range_record_t *range = range_records.push ();
 
-       unsigned int offset = feature_records.len;
+       unsigned int offset = feature_records.length;
 
        active_features.qsort ();
-       for (unsigned int j = 0; j < active_features.len; j++)
+       for (unsigned int j = 0; j < active_features.length; j++)
        {
-         if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
+         if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.length - 1].tagFeature)
          {
            feature_records.push (active_features[j].rec);
          }
          else
          {
            /* Overrides value for existing feature. */
-           feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
+           feature_records[feature_records.length - 1].lParameter = active_features[j].rec.lParameter;
          }
        }
 
        /* Will convert to pointer after all is ready, since feature_records.array
         * may move as we grow it. */
        range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
-       range->props.cotfRecords = feature_records.len - offset;
+       range->props.cotfRecords = feature_records.length - offset;
        range->index_first = last_index;
        range->index_last  = event->index - 1;
 
@@ -715,18 +698,18 @@ _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
       {
         active_feature_t *feature = active_features.find (&event->feature);
        if (feature)
-         active_features.remove (feature - active_features.arrayZ);
+         active_features.remove (feature - active_features.arrayZ ());
       }
     }
 
-    if (!range_records.len) /* No active feature found. */
+    if (!range_records.length) /* No active feature found. */
       num_features = 0;
 
     /* Fixup the pointers. */
-    for (unsigned int i = 0; i < range_records.len; i++)
+    for (unsigned int i = 0; i < range_records.length; i++)
     {
       range_record_t *range = &range_records[i];
-      range->props.potfRecords = feature_records.arrayZ + reinterpret_cast<uintptr_t> (range->props.potfRecords);
+      range->props.potfRecords = (OPENTYPE_FEATURE_RECORD *) feature_records + reinterpret_cast<uintptr_t> (range->props.potfRecords);
     }
   }
 
@@ -837,13 +820,19 @@ retry:
                                     script_tags,
                                     &item_count);
   if (unlikely (FAILED (hr)))
-    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
+    FAIL ("ScriptItemizeOpenType() failed: 0x%08lx", hr);
 
 #undef MAX_ITEMS
 
-  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
-  hb_auto_t<hb_vector_t<TEXTRANGE_PROPERTIES*> > range_properties;
-  hb_auto_t<hb_vector_t<int> > range_char_counts;
+  hb_tag_t lang_tag;
+  unsigned int lang_count = 1;
+  hb_ot_tags_from_script_and_language (buffer->props.script,
+                                      buffer->props.language,
+                                      nullptr, nullptr,
+                                      &lang_count, &lang_tag);
+  OPENTYPE_TAG language_tag = hb_uint32_swap (lang_count ? lang_tag : HB_TAG_NONE);
+  hb_vector_t<TEXTRANGE_PROPERTIES*> range_properties;
+  hb_vector_t<int> range_char_counts;
 
   unsigned int glyphs_offset = 0;
   unsigned int glyphs_len;
@@ -867,8 +856,8 @@ retry:
          range--;
        while (log_clusters[k] > range->index_last)
          range++;
-       if (!range_properties.len ||
-           &range->props != range_properties[range_properties.len - 1])
+       if (!range_properties.length ||
+           &range->props != range_properties[range_properties.length - 1])
        {
          TEXTRANGE_PROPERTIES **props = range_properties.push ();
          int *c = range_char_counts.push ();
@@ -883,7 +872,7 @@ retry:
        }
        else
        {
-         range_char_counts[range_char_counts.len - 1]++;
+         range_char_counts[range_char_counts.length - 1]++;
        }
 
        last_range = range;
@@ -900,9 +889,9 @@ retry:
                                     &items[i].a,
                                     script_tags[i],
                                     language_tag,
-                                    range_char_counts.arrayZ,
-                                    range_properties.arrayZ,
-                                    range_properties.len,
+                                    range_char_counts.arrayZ (),
+                                    range_properties.arrayZ (),
+                                    range_properties.length,
                                     pchars + chars_offset,
                                     item_chars_len,
                                     glyphs_size - glyphs_offset,
@@ -930,7 +919,7 @@ retry:
     }
     if (unlikely (FAILED (hr)))
     {
-      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
+      FAIL ("ScriptShapeOpenType() failed: 0x%08lx", hr);
     }
 
     for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
@@ -941,9 +930,9 @@ retry:
                                     &items[i].a,
                                     script_tags[i],
                                     language_tag,
-                                    range_char_counts.arrayZ,
-                                    range_properties.arrayZ,
-                                    range_properties.len,
+                                    range_char_counts.arrayZ (),
+                                    range_properties.arrayZ (),
+                                    range_properties.length,
                                     pchars + chars_offset,
                                     log_clusters + chars_offset,
                                     char_props + chars_offset,
@@ -956,7 +945,7 @@ retry:
                                     offsets + glyphs_offset,
                                     nullptr);
     if (unlikely (FAILED (hr)))
-      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
+      FAIL ("ScriptPlaceOpenType() failed: 0x%08lx", hr);
 
     if (DEBUG_ENABLED (UNISCRIBE))
       fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
@@ -975,13 +964,13 @@ retry:
 
   /* Calculate visual-clusters.  That's what we ship. */
   for (unsigned int i = 0; i < glyphs_len; i++)
-    vis_clusters[i] = -1;
+    vis_clusters[i] = (uint32_t) -1;
   for (unsigned int i = 0; i < buffer->len; i++) {
     uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
     *p = MIN (*p, buffer->info[i].cluster);
   }
   for (unsigned int i = 1; i < glyphs_len; i++)
-    if (vis_clusters[i] == -1)
+    if (vis_clusters[i] == (uint32_t) -1)
       vis_clusters[i] = vis_clusters[i - 1];
 
 #undef utf16_index
diff --git a/src/hb-utf-private.hh b/src/hb-utf-private.hh
deleted file mode 100644 (file)
index 211eb4d..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright © 2011,2012,2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UTF_PRIVATE_HH
-#define HB_UTF_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-struct hb_utf8_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-       const uint8_t *end,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    /* Written to only accept well-formed sequences.
-     * Based on ideas from ICU's U8_NEXT.
-     * Generates one "replacement" for each ill-formed byte. */
-
-    hb_codepoint_t c = *text++;
-
-    if (c > 0x7Fu)
-    {
-      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
-      {
-       unsigned int t1;
-       if (likely (text < end &&
-                   (t1 = text[0] - 0x80u) <= 0x3Fu))
-       {
-         c = ((c&0x1Fu)<<6) | t1;
-         text++;
-       }
-       else
-         goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
-      {
-       unsigned int t1, t2;
-       if (likely (1 < end - text &&
-                   (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                   (t2 = text[1] - 0x80u) <= 0x3Fu))
-       {
-         c = ((c&0xFu)<<12) | (t1<<6) | t2;
-         if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-           goto error;
-         text += 2;
-       }
-       else
-         goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
-      {
-       unsigned int t1, t2, t3;
-       if (likely (2 < end - text &&
-                   (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                   (t2 = text[1] - 0x80u) <= 0x3Fu &&
-                   (t3 = text[2] - 0x80u) <= 0x3Fu))
-       {
-         c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
-         if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
-           goto error;
-         text += 3;
-       }
-       else
-         goto error;
-      }
-      else
-       goto error;
-    }
-
-    *unicode = c;
-    return text;
-
-  error:
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-       const uint8_t *start,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    const uint8_t *end = text--;
-    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
-      text--;
-
-    if (likely (next (text, end, unicode, replacement) == end))
-      return text;
-
-    *unicode = replacement;
-    return end - 1;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    return ::strlen ((const char *) text);
-  }
-};
-
-
-struct hb_utf16_t
-{
-  typedef uint16_t codepoint_t;
-
-  static inline const uint16_t *
-  next (const uint16_t *text,
-       const uint16_t *end,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *text++;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c <= 0xDBFFu && text < end))
-    {
-      /* High-surrogate in c */
-      hb_codepoint_t l = *text;
-      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
-      {
-       /* Low-surrogate in l */
-       *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text++;
-        return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint16_t *
-  prev (const uint16_t *text,
-       const uint16_t *start,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *--text;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c >= 0xDC00u && start < text))
-    {
-      /* Low-surrogate in c */
-      hb_codepoint_t h = text[-1];
-      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
-      {
-        /* High-surrogate in h */
-        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text--;
-        return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-
-  static inline unsigned int
-  strlen (const uint16_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-template <bool validate=true>
-struct hb_utf32_t
-{
-  typedef uint32_t codepoint_t;
-
-  static inline const uint32_t *
-  next (const uint32_t *text,
-       const uint32_t *end HB_UNUSED,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *text++;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint32_t *
-  prev (const uint32_t *text,
-       const uint32_t *start HB_UNUSED,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *--text;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint32_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-struct hb_latin1_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-       const uint8_t *end HB_UNUSED,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement HB_UNUSED)
-  {
-    *unicode = *text++;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-       const uint8_t *start HB_UNUSED,
-       hb_codepoint_t *unicode,
-       hb_codepoint_t replacement)
-  {
-    *unicode = *--text;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-#endif /* HB_UTF_PRIVATE_HH */
diff --git a/src/hb-utf.hh b/src/hb-utf.hh
new file mode 100644 (file)
index 0000000..59ec75e
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright © 2011,2012,2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UTF_HH
+#define HB_UTF_HH
+
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+
+
+struct hb_utf8_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+       const codepoint_t *end,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    /* Written to only accept well-formed sequences.
+     * Based on ideas from ICU's U8_NEXT.
+     * Generates one "replacement" for each ill-formed byte. */
+
+    hb_codepoint_t c = *text++;
+
+    if (c > 0x7Fu)
+    {
+      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
+      {
+       unsigned int t1;
+       if (likely (text < end &&
+                   (t1 = text[0] - 0x80u) <= 0x3Fu))
+       {
+         c = ((c&0x1Fu)<<6) | t1;
+         text++;
+       }
+       else
+         goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
+      {
+       unsigned int t1, t2;
+       if (likely (1 < end - text &&
+                   (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                   (t2 = text[1] - 0x80u) <= 0x3Fu))
+       {
+         c = ((c&0xFu)<<12) | (t1<<6) | t2;
+         if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+           goto error;
+         text += 2;
+       }
+       else
+         goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
+      {
+       unsigned int t1, t2, t3;
+       if (likely (2 < end - text &&
+                   (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                   (t2 = text[1] - 0x80u) <= 0x3Fu &&
+                   (t3 = text[2] - 0x80u) <= 0x3Fu))
+       {
+         c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
+         if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
+           goto error;
+         text += 3;
+       }
+       else
+         goto error;
+      }
+      else
+       goto error;
+    }
+
+    *unicode = c;
+    return text;
+
+  error:
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+       const codepoint_t *start,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    const codepoint_t *end = text--;
+    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
+      text--;
+
+    if (likely (next (text, end, unicode, replacement) == end))
+      return text;
+
+    *unicode = replacement;
+    return end - 1;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  { return ::strlen ((const char *) text); }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    if (unicode <   0x0080u) return 1;
+    if (unicode <   0x0800u) return 2;
+    if (unicode <  0x10000u) return 3;
+    if (unicode < 0x110000u) return 4;
+    return 3;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+         const codepoint_t *end,
+         hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x0080u)
+     *text++ = unicode;
+    else if (unicode < 0x0800u)
+    {
+      if (end - text >= 2)
+      {
+       *text++ =  0xC0u + (0x1Fu & (unicode >>  6));
+       *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else if (unicode < 0x10000u)
+    {
+      if (end - text >= 3)
+      {
+       *text++ =  0xE0u + (0x0Fu & (unicode >> 12));
+       *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+       *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else
+    {
+      if (end - text >= 4)
+      {
+       *text++ =  0xF0u + (0x07u & (unicode >> 18));
+       *text++ =  0x80u + (0x3Fu & (unicode >> 12));
+       *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+       *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    return text;
+  }
+};
+
+
+template <typename TCodepoint>
+struct hb_utf16_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 2, "");
+  typedef TCodepoint codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+       const codepoint_t *end,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *text++;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c <= 0xDBFFu && text < end))
+    {
+      /* High-surrogate in c */
+      hb_codepoint_t l = *text;
+      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
+      {
+       /* Low-surrogate in l */
+       *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+        text++;
+        return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+       const codepoint_t *start,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *--text;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c >= 0xDC00u && start < text))
+    {
+      /* Low-surrogate in c */
+      hb_codepoint_t h = text[-1];
+      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
+      {
+        /* High-surrogate in h */
+        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+        text--;
+        return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    return unicode < 0x10000 ? 1 : 2;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+         const codepoint_t *end,
+         hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x10000u)
+     *text++ = unicode;
+    else if (end - text >= 2)
+    {
+      unicode -= 0x10000u;
+      *text++ =  0xD800u + (unicode >> 10);
+      *text++ =  0xDC00u + (unicode & 0x03FFu);
+    }
+    return text;
+  }
+};
+
+typedef hb_utf16_xe_t<uint16_t> hb_utf16_t;
+typedef hb_utf16_xe_t<OT::HBUINT16> hb_utf16_be_t;
+
+
+template <typename TCodepoint, bool validate=true>
+struct hb_utf32_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 4, "");
+  typedef TCodepoint codepoint_t;
+
+  static const TCodepoint *
+  next (const TCodepoint *text,
+       const TCodepoint *end HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *text++;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static const TCodepoint *
+  prev (const TCodepoint *text,
+       const TCodepoint *start HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *--text;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const TCodepoint *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+         const codepoint_t *end HB_UNUSED,
+         hb_codepoint_t unicode)
+  {
+    if (validate && unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    *text++ = unicode;
+    return text;
+  }
+};
+
+typedef hb_utf32_xe_t<uint32_t> hb_utf32_t;
+typedef hb_utf32_xe_t<uint32_t, false> hb_utf32_novalidate_t;
+
+
+struct hb_latin1_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+       const codepoint_t *end HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+       const codepoint_t *start HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *--text;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+         const codepoint_t *end HB_UNUSED,
+         hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0100u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+
+struct hb_ascii_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+       const codepoint_t *end HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+       const codepoint_t *start HB_UNUSED,
+       hb_codepoint_t *unicode,
+       hb_codepoint_t replacement)
+  {
+    *unicode = *--text;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+         const codepoint_t *end HB_UNUSED,
+         hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0080u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+#endif /* HB_UTF_HH */
diff --git a/src/hb-vector.hh b/src/hb-vector.hh
new file mode 100644 (file)
index 0000000..2fd739b
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright © 2017,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_VECTOR_HH
+#define HB_VECTOR_HH
+
+#include "hb.hh"
+#include "hb-array.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_vector_t
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
+  hb_vector_t ()  { init (); }
+  ~hb_vector_t () { fini (); }
+
+  unsigned int length;
+  private:
+  int allocated; /* == -1 means allocation failed. */
+  Type *arrayZ_;
+  public:
+
+  void init ()
+  {
+    allocated = length = 0;
+    arrayZ_ = nullptr;
+  }
+
+  void fini ()
+  {
+    if (arrayZ_)
+      free (arrayZ_);
+    init ();
+  }
+  void fini_deep ()
+  {
+    Type *array = arrayZ();
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      array[i].fini ();
+    fini ();
+  }
+
+  const Type * arrayZ () const { return arrayZ_; }
+        Type * arrayZ ()       { return arrayZ_; }
+
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Crap (Type);
+    return arrayZ()[i];
+  }
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Null(Type);
+    return arrayZ()[i];
+  }
+
+  explicit_operator bool () const { return length; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ(), length); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  hb_sorted_array_t<Type> as_sorted_array ()
+  { return hb_sorted_array (arrayZ(), length); }
+  hb_sorted_array_t<const Type> as_sorted_array () const
+  { return hb_sorted_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+
+  template <typename T> explicit_operator T * () { return arrayZ(); }
+  template <typename T> explicit_operator const T * () const { return arrayZ(); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  Type * operator  + (unsigned int i) { return arrayZ() + i; }
+  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
+
+  Type *push ()
+  {
+    if (unlikely (!resize (length + 1)))
+      return &Crap(Type);
+    return &arrayZ()[length - 1];
+  }
+  Type *push (const Type& v)
+  {
+    Type *p = push ();
+    *p = v;
+    return p;
+  }
+
+  bool in_error () const { return allocated < 0; }
+
+  /* Allocate for size but don't adjust length. */
+  bool alloc (unsigned int size)
+  {
+    if (unlikely (allocated < 0))
+      return false;
+
+    if (likely (size <= (unsigned) allocated))
+      return true;
+
+    /* Reallocate */
+
+    unsigned int new_allocated = allocated;
+    while (size >= new_allocated)
+      new_allocated += (new_allocated >> 1) + 8;
+
+    Type *new_array = nullptr;
+    bool overflows =
+      (int) new_allocated < 0 ||
+      (new_allocated < (unsigned) allocated) ||
+      hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
+    if (likely (!overflows))
+      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
+
+    if (unlikely (!new_array))
+    {
+      allocated = -1;
+      return false;
+    }
+
+    arrayZ_ = new_array;
+    allocated = new_allocated;
+
+    return true;
+  }
+
+  bool resize (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+    if (!alloc (size))
+      return false;
+
+    if (size > length)
+      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
+
+    length = size;
+    return true;
+  }
+
+  void pop ()
+  {
+    if (!length) return;
+    length--;
+  }
+
+  void remove (unsigned int i)
+  {
+    if (unlikely (i >= length))
+      return;
+    Type *array = arrayZ();
+    memmove (static_cast<void *> (&array[i]),
+            static_cast<void *> (&array[i + 1]),
+            (length - i - 1) * sizeof (Type));
+    length--;
+  }
+
+  void shrink (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+     if (size < length)
+       length = size;
+  }
+
+  template <typename T>
+  Type *find (T v)
+  {
+    Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+       return &array[i];
+    return nullptr;
+  }
+  template <typename T>
+  const Type *find (T v) const
+  {
+    const Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+       return &array[i];
+    return nullptr;
+  }
+
+  void qsort (int (*cmp)(const void*, const void*))
+  { as_array ().qsort (cmp); }
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  { return as_array ().lsearch (x, not_found); }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_array ().lsearch (x, not_found); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  { return as_sorted_array ().bsearch (x, not_found); }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_sorted_array ().bsearch (x, not_found); }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                    hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                    unsigned int to_store = (unsigned int) -1) const
+  { return as_sorted_array ().bfind (x, i, not_found, to_store); }
+};
+
+
+#endif /* HB_VECTOR_HH */
index 2180d84..13db8ce 100644 (file)
 HB_BEGIN_DECLS
 
 
-#define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 8
+#define HB_VERSION_MAJOR 2
+#define HB_VERSION_MINOR 3
 #define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "1.8.1"
+#define HB_VERSION_STRING "2.3.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
        ((major)*10000+(minor)*100+(micro) <= \
index 8f322bc..9fb4100 100644 (file)
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
+#include "hb.hh"
 
 #if defined(HB_ATOMIC_INT_NIL)
 #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
-#error "Check hb-atomic-private.hh for possible resolutions."
+#error "Check hb-atomic.hh for possible resolutions."
 #endif
 
 #if defined(HB_MUTEX_IMPL_NIL)
 #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
-#error "Check hb-mutex-private.hh for possible resolutions."
+#error "Check hb-mutex.hh for possible resolutions."
 #endif
index fc75a69..c5e7072 100644 (file)
--- a/src/hb.h
+++ b/src/hb.h
 #define HB_H
 #define HB_H_IN
 
-#ifndef HB_EXTERN
-#define HB_EXTERN extern
-#endif
-
 #include "hb-blob.h"
 #include "hb-buffer.h"
 #include "hb-common.h"
diff --git a/src/hb.hh b/src/hb.hh
new file mode 100644 (file)
index 0000000..5b66ba8
--- /dev/null
+++ b/src/hb.hh
@@ -0,0 +1,658 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2011,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
+ */
+
+#ifndef HB_HH
+#define HB_HH
+
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
+#if defined(_MSC_VER)
+#pragma warning( disable: 4068 ) /* Unknown pragma */
+#endif
+#if defined(__GNUC__) || defined(__clang__)
+/* Rules:
+ *
+ * - All pragmas are declared GCC even if they are clang ones.  Otherwise GCC
+ *   nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯
+ *
+ * - Within each category, keep sorted.
+ *
+ * - Warnings whose scope can be expanded in future compiler versions shall
+ *   be declared as "warning".  Otherwise, either ignored or error.
+ */
+
+/* Setup.  Don't sort order within this category. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wall"
+#pragma GCC diagnostic warning "-Wextra"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Wunknown-warning-option"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+//#pragma GCC diagnostic warning "-Weverything"
+#endif
+
+/* Error.  Should never happen. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
+#pragma GCC diagnostic error   "-Wc++11-narrowing"
+#pragma GCC diagnostic error   "-Wcast-align"
+#pragma GCC diagnostic error   "-Wcast-function-type"
+#pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
+#pragma GCC diagnostic error   "-Wformat-security"
+#pragma GCC diagnostic error   "-Wimplicit-function-declaration"
+#pragma GCC diagnostic error   "-Winit-self"
+#pragma GCC diagnostic error   "-Wmissing-braces"
+#pragma GCC diagnostic error   "-Wmissing-declarations"
+#pragma GCC diagnostic error   "-Wmissing-prototypes"
+#pragma GCC diagnostic error   "-Wnested-externs"
+#pragma GCC diagnostic error   "-Wold-style-definition"
+#pragma GCC diagnostic error   "-Wpointer-arith"
+#pragma GCC diagnostic error   "-Wredundant-decls"
+#pragma GCC diagnostic error   "-Wreorder"
+#pragma GCC diagnostic error   "-Wsign-compare"
+#pragma GCC diagnostic error   "-Wstrict-prototypes"
+#pragma GCC diagnostic error   "-Wstring-conversion"
+#pragma GCC diagnostic error   "-Wswitch-enum"
+#pragma GCC diagnostic error   "-Wtautological-overlap-compare"
+#pragma GCC diagnostic error   "-Wunneeded-internal-declaration"
+#pragma GCC diagnostic error   "-Wunused"
+#pragma GCC diagnostic error   "-Wunused-local-typedefs"
+#pragma GCC diagnostic error   "-Wunused-value"
+#pragma GCC diagnostic error   "-Wunused-variable"
+#pragma GCC diagnostic error   "-Wvla"
+#pragma GCC diagnostic error   "-Wwrite-strings"
+#endif
+
+/* Warning.  To be investigated if happens. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
+#pragma GCC diagnostic warning "-Wdisabled-optimization"
+#pragma GCC diagnostic warning "-Wformat=2"
+#pragma GCC diagnostic warning "-Wignored-pragma-optimize"
+#pragma GCC diagnostic warning "-Wlogical-op"
+#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
+#pragma GCC diagnostic warning "-Wmissing-format-attribute"
+#pragma GCC diagnostic warning "-Wundef"
+#endif
+
+/* Ignored currently, but should be fixed at some point. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wconversion"                  // TODO fix
+#pragma GCC diagnostic ignored "-Wformat-signedness"           // TODO fix
+#pragma GCC diagnostic ignored "-Wshadow"                      // TODO fix
+#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"   // TODO fix
+#pragma GCC diagnostic ignored "-Wunused-parameter"            // TODO fix
+#endif
+
+/* Ignored intentionally. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
+ * config.h.in.  Copied here for the convenience of those embedding
+ * HarfBuzz and not using our build system.
+ */
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+#if defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+#define HB_EXTERN __declspec (dllexport) extern
+#endif
+
+#include "hb.h"
+#define HB_H_IN
+#include "hb-ot.h"
+#define HB_OT_H_IN
+#include "hb-aat.h"
+#define HB_AAT_H_IN
+
+#include "hb-aat.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+#include <intrin.h>
+#endif
+
+#define HB_PASTE1(a,b) a##b
+#define HB_PASTE(a,b) HB_PASTE1(a,b)
+
+
+/* Compile-time custom allocator support. */
+
+#if defined(hb_malloc_impl) \
+ && defined(hb_calloc_impl) \
+ && defined(hb_realloc_impl) \
+ && defined(hb_free_impl)
+extern "C" void* hb_malloc_impl(size_t size);
+extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
+extern "C" void* hb_realloc_impl(void *ptr, size_t size);
+extern "C" void  hb_free_impl(void *ptr);
+#define malloc hb_malloc_impl
+#define calloc hb_calloc_impl
+#define realloc hb_realloc_impl
+#define free hb_free_impl
+
+#if defined(hb_memalign_impl)
+extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
+#define posix_memalign hb_memalign_impl
+#else
+#undef HAVE_POSIX_MEMALIGN
+#endif
+
+#endif
+
+
+/*
+ * Compiler attributes
+ */
+
+#if __cplusplus < 201103L
+
+#ifndef nullptr
+#define nullptr NULL
+#endif
+
+#ifndef constexpr
+#define constexpr const
+#endif
+
+#ifndef static_assert
+#define static_assert(e, msg) \
+       HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
+#endif // static_assert
+
+#if defined(__GNUC__)
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+#define thread_local __thread
+#endif
+#else
+#define thread_local
+#endif
+
+template <typename T>
+struct _hb_alignof
+{
+  struct s
+  {
+    char c;
+    T t;
+  };
+  static constexpr size_t value = offsetof (s, t);
+};
+#ifndef alignof
+#define alignof(x) (_hb_alignof<x>::value)
+#endif
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator operator
+#endif
+
+#else /* __cplusplus >= 201103L */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator explicit operator
+#endif
+
+#endif /* __cplusplus < 201103L */
+
+
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
+#define likely(expr) (__builtin_expect (!!(expr), 1))
+#define unlikely(expr) (__builtin_expect (!!(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
+#if !defined(__GNUC__) && !defined(__clang__)
+#undef __attribute__
+#define __attribute__(x)
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_PURE_FUNC   __attribute__((pure))
+#define HB_CONST_FUNC  __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define HB_PURE_FUNC
+#define HB_CONST_FUNC
+#define HB_PRINTF_FUNC(format_idx, arg_idx)
+#endif
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define HB_UNUSED      __attribute__((unused))
+#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
+#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
+#else
+#define HB_UNUSED
+#endif
+
+#ifndef HB_INTERNAL
+# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
+#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
+# elif defined(__MINGW32__)
+   /* We use -export-symbols on mingw32, since it does not support visibility attributes. */
+#  define HB_INTERNAL
+# elif defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+   /* We do not try to export internal symbols on Visual Studio */
+#  define HB_INTERNAL
+#else
+#  define HB_INTERNAL
+#  define HB_NO_VISIBILITY 1
+# endif
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_FUNC __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define HB_FUNC __FUNCSIG__
+#else
+#define HB_FUNC __func__
+#endif
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
+/* https://github.com/harfbuzz/harfbuzz/issues/630 */
+#define __restrict
+#endif
+
+/*
+ * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
+ * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
+ * cases that fall through without a break or return statement. HB_FALLTHROUGH
+ * is only needed on cases that have code:
+ *
+ * switch (foo) {
+ *   case 1: // These cases have no code. No fallthrough annotations are needed.
+ *   case 2:
+ *   case 3:
+ *     foo = 4; // This case has code, so a fallthrough annotation is needed:
+ *     HB_FALLTHROUGH;
+ *   default:
+ *     return foo;
+ * }
+ */
+#if defined(__clang__) && __cplusplus >= 201103L
+   /* clang's fallthrough annotations are only available starting in C++11. */
+#  define HB_FALLTHROUGH [[clang::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+   /* GNU fallthrough attribute is available from GCC7 */
+#  define HB_FALLTHROUGH __attribute__((fallthrough))
+#elif defined(_MSC_VER)
+   /*
+    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
+    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
+    */
+#  include <sal.h>
+#  define HB_FALLTHROUGH __fallthrough
+#else
+#  define HB_FALLTHROUGH /* FALLTHROUGH */
+#endif
+
+#if defined(__clang__)
+/* Disable certain sanitizer errors. */
+/* https://github.com/harfbuzz/harfbuzz/issues/1247 */
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
+#else
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+#endif
+
+
+#ifdef _WIN32
+   /* We need Windows Vista for both Uniscribe backend and for
+    * MemoryBarrier.  We don't support compiling on Windows XP,
+    * though we run on it fine. */
+#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
+#    undef _WIN32_WINNT
+#  endif
+#  ifndef _WIN32_WINNT
+#    if !defined(WINAPI_FAMILY) || !(WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#      define _WIN32_WINNT 0x0600
+#    endif
+#  endif
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN 1
+#  endif
+#  ifndef STRICT
+#    define STRICT 1
+#  endif
+
+#  if defined(_WIN32_WCE)
+     /* Some things not defined on Windows CE. */
+#    define vsnprintf _vsnprintf
+#    define getenv(Name) nullptr
+#    if _WIN32_WCE < 0x800
+#      define setlocale(Category, Locale) "C"
+static int errno = 0; /* Use something better? */
+#    endif
+#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#    define getenv(Name) nullptr
+#  endif
+#  if defined(_MSC_VER) && _MSC_VER < 1900
+#    define snprintf _snprintf
+#  endif
+#endif
+
+#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
+/* atexit() is only safe to be called from shared libraries on certain
+ * platforms.  Whitelist.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
+#  if defined(__linux) && defined(__GLIBC_PREREQ)
+#    if __GLIBC_PREREQ(2,3)
+/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
+#      define HB_USE_ATEXIT 1
+#    endif
+#  elif defined(_MSC_VER) || defined(__MINGW32__)
+/* For MSVC:
+ * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
+ * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
+ * mingw32 headers say atexit is safe to use in shared libraries.
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__ANDROID__)
+/* This is available since Android NKD r8 or r8b:
+ * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__APPLE__)
+/* For macOS and related platforms, the atexit man page indicates
+ * that it will be invoked when the library is unloaded, not only
+ * at application exit.
+ */
+#    define HB_USE_ATEXIT 1
+#  endif
+#endif
+#ifdef HB_NO_ATEXIT
+#  undef HB_USE_ATEXIT
+#endif
+#ifndef HB_USE_ATEXIT
+#  define HB_USE_ATEXIT 0
+#endif
+
+#define HB_STMT_START do
+#define HB_STMT_END   while (0)
+
+/* Static-assert as expression. */
+template <unsigned int cond> class hb_assert_constant_t;
+template <> class hb_assert_constant_t<1> {};
+#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
+
+/* Lets assert int types.  Saves trouble down the road. */
+static_assert ((sizeof (int8_t) == 1), "");
+static_assert ((sizeof (uint8_t) == 1), "");
+static_assert ((sizeof (int16_t) == 2), "");
+static_assert ((sizeof (uint16_t) == 2), "");
+static_assert ((sizeof (int32_t) == 4), "");
+static_assert ((sizeof (uint32_t) == 4), "");
+static_assert ((sizeof (int64_t) == 8), "");
+static_assert ((sizeof (uint64_t) == 8), "");
+static_assert ((sizeof (hb_codepoint_t) == 4), "");
+static_assert ((sizeof (hb_position_t) == 4), "");
+static_assert ((sizeof (hb_mask_t) == 4), "");
+static_assert ((sizeof (hb_var_int_t) == 4), "");
+
+
+#if __cplusplus >= 201103L
+
+/* We only enable these with C++11 or later, since earlier language
+ * does not allow structs with constructors in unions, and we need
+ * those. */
+
+#define HB_NO_COPY_ASSIGN(TypeName) \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) \
+  TypeName(); \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(); \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(); \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+
+#else /* __cpluspplus >= 201103L */
+
+#define HB_NO_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+
+#endif /* __cpluspplus >= 201103L */
+
+
+/*
+ * Compiler-assisted vectorization parameters.
+ */
+
+/*
+ * Disable vectorization for now.  To correctly use them, we should
+ * use posix_memalign() to allocate in hb_vector_t.  Otherwise, can
+ * cause misaligned access.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
+ */
+#if !defined(HB_VECTOR_SIZE)
+#  define HB_VECTOR_SIZE 0
+#endif
+
+/* The `vector_size' attribute was introduced in gcc 3.1. */
+#if !defined(HB_VECTOR_SIZE)
+#  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
+#    define HB_VECTOR_SIZE 128
+#  else
+#    define HB_VECTOR_SIZE 0
+#  endif
+#endif
+static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
+static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
+#if HB_VECTOR_SIZE
+typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
+#else
+typedef uint64_t hb_vector_size_impl_t;
+#endif
+
+
+/* HB_NDEBUG disables some sanity checks that are very safe to disable and
+ * should be disabled in production systems.  If NDEBUG is defined, enable
+ * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
+ * light-weight) to be enabled, then HB_DEBUG can be defined to disable
+ * the costlier checks. */
+#ifdef NDEBUG
+#define HB_NDEBUG 1
+#endif
+
+
+/* Flags */
+
+/* Enable bitwise ops on enums marked as flags_t */
+/* To my surprise, looks like the function resolver is happy to silently cast
+ * one enum to another...  So this doesn't provide the type-checking that I
+ * originally had in mind... :(.
+ *
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
+ */
+#ifdef _MSC_VER
+# pragma warning(disable:4200)
+# pragma warning(disable:4800)
+#endif
+#define HB_MARK_AS_FLAG_T(T) \
+       extern "C++" { \
+         static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
+         static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
+         static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
+         static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
+         static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
+         static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
+         static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
+       } \
+       static_assert (true, "")
+
+/* Useful for set-operations on small enums.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
+#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
+#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
+#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
+#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
+
+
+/* Size signifying variable-sized array */
+#define VAR 1
+
+
+/* fallback for round() */
+static inline double
+_hb_round (double x)
+{
+  if (x >= 0)
+    return floor (x + 0.5);
+  else
+    return ceil (x - 0.5);
+}
+#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
+#define round(x) _hb_round(x)
+#endif
+
+
+/* fallback for posix_memalign() */
+static inline int
+_hb_memalign(void **memptr, size_t alignment, size_t size)
+{
+  if (unlikely (0 != (alignment & (alignment - 1)) ||
+               !alignment ||
+               0 != (alignment & (sizeof (void *) - 1))))
+    return EINVAL;
+
+  char *p = (char *) malloc (size + alignment - 1);
+  if (unlikely (!p))
+    return ENOMEM;
+
+  size_t off = (size_t) p & (alignment - 1);
+  if (off)
+    p += alignment - off;
+
+  *memptr = (void *) p;
+
+  return 0;
+}
+#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
+#define posix_memalign _hb_memalign
+#endif
+
+
+/*
+ * For lack of a better place, put Zawgyi script hack here.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162
+ */
+
+#define HB_SCRIPT_MYANMAR_ZAWGYI       ((hb_script_t) HB_TAG ('Q','a','a','g'))
+
+
+/* Some really basic things everyone wants. */
+template <typename T> struct hb_remove_const { typedef T value; };
+template <typename T> struct hb_remove_const<const T> { typedef T value; };
+#define hb_remove_const(T) hb_remove_const<T>::value
+template <typename T> struct hb_remove_reference { typedef T value; };
+template <typename T> struct hb_remove_reference<T &> { typedef T value; };
+#define hb_remove_reference(T) hb_remove_reference<T>::value
+template <typename T> struct hb_remove_pointer { typedef T value; };
+template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
+#define hb_remove_pointer(T) hb_remove_pointer<T>::value
+
+
+/* Headers we include for everyone.  Keep topologically sorted by dependency.
+ * They express dependency amongst themselves, but no other file should include
+ * them directly.*/
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-null.hh"
+#include "hb-dsalgs.hh"        // Requires: hb-null
+#include "hb-iter.hh"  // Requires: hb-null
+#include "hb-debug.hh" // Requires: hb-atomic hb-dsalgs
+#include "hb-array.hh" // Requires: hb-dsalgs hb-iter hb-null
+#include "hb-vector.hh"        // Requires: hb-array hb-null
+#include "hb-object.hh"        // Requires: hb-atomic hb-mutex hb-vector
+
+#endif /* HB_HH */
index ca0fcc5..490b76e 100644 (file)
@@ -25,9 +25,9 @@
  */
 
 #include "hb-static.cc"
-#include "hb-open-file-private.hh"
+#include "hb-open-file.hh"
 #include "hb-ot-layout-gdef-table.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 #ifdef HAVE_GLIB
 #include <glib.h>
@@ -51,10 +51,9 @@ main (int argc, char **argv)
   const char *font_data = hb_blob_get_data (blob, &len);
   printf ("Opened font file %s: %d bytes long\n", argv[1], len);
 
-  Sanitizer<OpenTypeFontFile> sanitizer;
-  hb_blob_t *font_blob = sanitizer.sanitize (blob);
+  hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob<OpenTypeFontFile> (blob);
   const OpenTypeFontFile* sanitized = font_blob->as<OpenTypeFontFile> ();
-  if (sanitized == &Null(OpenTypeFontFile))
+  if (!font_blob->data)
   {
     printf ("Sanitization of the file wasn't successful. Exit");
     return 1;
@@ -78,6 +77,9 @@ main (int argc, char **argv)
   case OpenTypeFontFile::Typ1Tag:
     printf ("Obsolete Apple Type1 font in SFNT container\n");
     break;
+  case OpenTypeFontFile::DFontTag:
+    printf ("DFont Mac Resource Fork\n");
+    break;
   default:
     printf ("Unknown font format\n");
     break;
index 39eb13d..a91f4f7 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb.h"
 #include "hb-ot.h"
diff --git a/src/test-iter.cc b/src/test-iter.cc
new file mode 100644 (file)
index 0000000..05430b0
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-iter.hh"
+
+#include "hb-array.hh"
+#include "hb-set.hh"
+
+
+template <typename T>
+struct array_iter_t : hb_iter_t<array_iter_t<T>, T>, hb_iter_mixin_t<array_iter_t<T>, T>
+{
+  array_iter_t (hb_array_t<T> arr_) : arr (arr_) {}
+
+  typedef T __item_type__;
+  T& __item_at__ (unsigned i) const { return arr[i]; }
+  void __forward__ (unsigned n) { arr += n; }
+  void __rewind__ (unsigned n) { arr -= n; }
+  unsigned __len__ () const { return arr.length; }
+  bool __random_access__ () const { return true; }
+
+  private:
+  hb_array_t<T> arr;
+};
+
+template <typename T>
+struct some_array_t
+{
+  some_array_t (hb_array_t<T> arr_) : arr (arr_) {}
+
+  typedef array_iter_t<T> iter_t;
+  array_iter_t<T> iter () { return array_iter_t<T> (arr); }
+  operator array_iter_t<T> () { return iter (); }
+  operator hb_iter_t<array_iter_t<T> > () { return iter (); }
+
+  private:
+  hb_array_t<T> arr;
+};
+
+int
+main (int argc, char **argv)
+{
+  const int src[10] = {};
+  int dst[20];
+  hb_vector_t<int> v;
+
+  array_iter_t<const int> s (src); /* Implicit conversion from static array. */
+  array_iter_t<const int> s2 (v); /* Implicit conversion from vector. */
+  array_iter_t<int> t (dst);
+
+  some_array_t<const int> a (src);
+
+  s2 = s;
+
+  hb_fill (t, 42);
+  hb_copy (t, s);
+ // hb_copy (t, a.iter ());
+
+  return 0;
+}
diff --git a/src/test-name-table.cc b/src/test-name-table.cc
new file mode 100644 (file)
index 0000000..518e4eb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-ot.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  if (argc != 2) {
+    fprintf (stderr, "usage: %s font-file\n", argv[0]);
+    exit (1);
+  }
+
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
+  hb_blob_destroy (blob);
+  blob = nullptr;
+
+  unsigned int count;
+  const hb_ot_name_entry_t *entries = hb_ot_name_list_names (face, &count);
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    printf ("%u        %s      ",
+           entries[i].name_id,
+           hb_language_to_string (entries[i].language));
+
+    char buf[64];
+    unsigned int buf_size = sizeof (buf);
+    hb_ot_name_get_utf8 (face,
+                        entries[i].name_id,
+                        entries[i].language,
+                        &buf_size,
+                        buf);
+
+    printf ("%s\n", buf);
+  }
+
+  hb_face_destroy (face);
+
+  return count ? 0 : 1;
+}
diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc
new file mode 100644 (file)
index 0000000..4050a66
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Khaled Hosny
+ *
+ *  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.
+ */
+
+#include "hb.h"
+#include "hb-ot.h"
+
+#include "hb-ft.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#include <cairo.h>
+#include <cairo-ft.h>
+#include <cairo-svg.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+static void
+svg_dump (hb_face_t *face, unsigned int face_index)
+{
+  unsigned glyph_count = hb_face_get_glyph_count (face);
+
+  for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
+  {
+    hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id);
+
+    if (hb_blob_get_length (blob) == 0) continue;
+
+    unsigned int length;
+    const char *data = hb_blob_get_data (blob, &length);
+
+    char output_path[255];
+    sprintf (output_path, "out/svg-%u-%u.svg%s",
+            glyph_id,
+            face_index,
+            // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
+            (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : "");
+
+    FILE *f = fopen (output_path, "wb");
+    fwrite (data, 1, length, f);
+    fclose (f);
+
+    hb_blob_destroy (blob);
+  }
+}
+
+/* _png API is so easy to use unlike the below code, don't get confused */
+static void
+png_dump (hb_face_t *face, unsigned int face_index)
+{
+  unsigned glyph_count = hb_face_get_glyph_count (face);
+  hb_font_t *font = hb_font_create (face);
+
+  /* scans the font for strikes */
+  unsigned int sample_glyph_id;
+  /* we don't care about different strikes for different glyphs at this point */
+  for (sample_glyph_id = 0; sample_glyph_id < glyph_count; sample_glyph_id++)
+  {
+    hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
+    unsigned int blob_length = hb_blob_get_length (blob);
+    hb_blob_destroy (blob);
+    if (blob_length != 0)
+      break;
+  }
+
+  unsigned int upem = hb_face_get_upem (face);
+  unsigned int blob_length = 0;
+  unsigned int strike = 0;
+  for (unsigned int ppem = 1; ppem < upem; ppem++)
+  {
+    hb_font_set_ppem (font, ppem, ppem);
+    hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id);
+    unsigned int new_blob_length = hb_blob_get_length (blob);
+    hb_blob_destroy (blob);
+    if (new_blob_length != blob_length)
+    {
+      for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
+      {
+       hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id);
+
+       if (hb_blob_get_length (blob) == 0) continue;
+
+       unsigned int length;
+       const char *data = hb_blob_get_data (blob, &length);
+
+       char output_path[255];
+       sprintf (output_path, "out/png-%u-%u-%u.png", glyph_id, strike, face_index);
+
+       FILE *f = fopen (output_path, "wb");
+       fwrite (data, 1, length, f);
+       fclose (f);
+
+       hb_blob_destroy (blob);
+      }
+
+      strike++;
+      blob_length = new_blob_length;
+    }
+  }
+
+  hb_font_destroy (font);
+}
+
+static void
+layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int face_index)
+{
+  unsigned int upem = hb_face_get_upem (face);
+
+  unsigned glyph_count = hb_face_get_glyph_count (face);
+  for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid)
+  {
+    unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, NULL, NULL);
+    if (!num_layers)
+      continue;
+
+    hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t));
+
+    hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers);
+    if (num_layers)
+    {
+      // Measure
+      cairo_text_extents_t extents;
+      {
+       cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+       cairo_t *cr = cairo_create (surface);
+       cairo_set_font_face (cr, cairo_face);
+       cairo_set_font_size (cr, upem);
+
+       cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
+       for (unsigned int j = 0; j < num_layers; ++j)
+         glyphs[j].index = layers[j].glyph;
+       cairo_glyph_extents (cr, glyphs, num_layers, &extents);
+       free (glyphs);
+       cairo_surface_destroy (surface);
+       cairo_destroy (cr);
+      }
+
+      // Add a slight margin
+      extents.width += extents.width / 10;
+      extents.height += extents.height / 10;
+      extents.x_bearing -= extents.width / 20;
+      extents.y_bearing -= extents.height / 20;
+
+      // Render
+      unsigned int palette_count = hb_ot_color_palette_get_count (face);
+      for (unsigned int palette = 0; palette < palette_count; palette++)
+      {
+       unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, NULL, NULL);
+       if (!num_colors)
+         continue;
+
+       hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t));
+       hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors);
+       if (num_colors)
+       {
+         char output_path[255];
+         sprintf (output_path, "out/colr-%u-%u-%u.svg", gid, palette, face_index);
+
+         cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
+         cairo_t *cr = cairo_create (surface);
+         cairo_set_font_face (cr, cairo_face);
+         cairo_set_font_size (cr, upem);
+
+         for (unsigned int layer = 0; layer < num_layers; ++layer)
+         {
+           hb_color_t color = 0x000000FF;
+           if (layers[layer].color_index != 0xFFFF)
+             color = colors[layers[layer].color_index];
+           cairo_set_source_rgba (cr,
+                                  hb_color_get_red (color) / 255.,
+                                  hb_color_get_green (color) / 255.,
+                                  hb_color_get_blue (color) / 255.,
+                                  hb_color_get_alpha (color) / 255.);
+
+           cairo_glyph_t glyph;
+           glyph.index = layers[layer].glyph;
+           glyph.x = -extents.x_bearing;
+           glyph.y = -extents.y_bearing;
+           cairo_show_glyphs (cr, &glyph, 1);
+         }
+
+         cairo_surface_destroy (surface);
+         cairo_destroy (cr);
+       }
+       free (colors);
+      }
+    }
+
+    free (layers);
+  }
+}
+
+static void
+dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
+            unsigned int num_glyphs, unsigned int face_index)
+{
+  for (unsigned int i = 0; i < num_glyphs; ++i)
+  {
+    cairo_text_extents_t extents;
+    cairo_glyph_t glyph = {0};
+    glyph.index = i;
+
+    // Measure
+    {
+      cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+      cairo_t *cr = cairo_create (surface);
+      cairo_set_font_face (cr, cairo_face);
+      cairo_set_font_size (cr, upem);
+
+      cairo_glyph_extents (cr, &glyph, 1, &extents);
+      cairo_surface_destroy (surface);
+      cairo_destroy (cr);
+    }
+
+    // Add a slight margin
+    extents.width += extents.width / 10;
+    extents.height += extents.height / 10;
+    extents.x_bearing -= extents.width / 20;
+    extents.y_bearing -= extents.height / 20;
+
+    // Render
+    {
+      char output_path[255];
+      sprintf (output_path, "out/%u-%u.svg", face_index, i);
+      cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
+      cairo_t *cr = cairo_create (surface);
+      cairo_set_font_face (cr, cairo_face);
+      cairo_set_font_size (cr, upem);
+      glyph.x = -extents.x_bearing;
+      glyph.y = -extents.y_bearing;
+      cairo_show_glyphs (cr, &glyph, 1);
+      cairo_surface_destroy (surface);
+      cairo_destroy (cr);
+    }
+  }
+}
+
+int
+main (int argc, char **argv)
+{
+  if (argc != 2) {
+    fprintf (stderr, "usage: %s font-file.ttf\n"
+                    "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n",
+                    argv[0], argv[0]);
+    exit (1);
+  }
+
+
+  FILE *font_name_file = fopen ("out/.dumped_font_name", "r");
+  if (font_name_file != NULL)
+  {
+    fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n");
+    exit (1);
+  }
+
+  font_name_file = fopen ("out/.dumped_font_name", "w");
+  if (font_name_file == NULL)
+  {
+    fprintf (stderr, "./out is not accessible as a folder, create it please\n");
+    exit (1);
+  }
+  fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
+  fclose (font_name_file);
+
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+  unsigned int num_faces = hb_face_count (blob);
+  if (num_faces == 0)
+  {
+    fprintf (stderr, "error: The file (%s) was corrupted, empty or not found", argv[1]);
+    exit (1);
+  }
+
+  for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++)
+  {
+    hb_face_t *face = hb_face_create (blob, face_index);
+    hb_font_t *font = hb_font_create (face);
+
+    if (hb_ot_color_has_png (face)) printf ("Dumping png (cbdt/sbix)...\n");
+    png_dump (face, face_index);
+
+    if (hb_ot_color_has_svg (face)) printf ("Dumping svg...\n");
+    svg_dump (face, face_index);
+
+    cairo_font_face_t *cairo_face;
+    {
+      FT_Library library;
+      FT_Init_FreeType (&library);
+      FT_Face ft_face;
+      FT_New_Face (library, argv[1], 0, &ft_face);
+      cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+    }
+    if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
+      printf ("Dumping layered color glyphs...\n");
+    layered_glyph_dump (face, cairo_face, face_index);
+
+    unsigned int num_glyphs = hb_face_get_glyph_count (face);
+    unsigned int upem = hb_face_get_upem (face);
+
+    // disabled when color font as cairo rendering of NotoColorEmoji is soooo slow
+    if (!hb_ot_color_has_layers (face) &&
+        !hb_ot_color_has_png (face) &&
+        !hb_ot_color_has_svg (face))
+      dump_glyphs (cairo_face, upem, num_glyphs, face_index);
+
+    hb_font_destroy (font);
+    hb_face_destroy (face);
+    }
+
+  hb_blob_destroy (blob);
+
+  return 0;
+}
index 3c43852..12eec61 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb.h"
 #include "hb-ot.h"
@@ -46,7 +46,7 @@ main (int argc, char **argv)
   blob = nullptr;
 
   unsigned int p[5];
-  bool ret = hb_ot_layout_get_size_params (face, p, p+1, p+2, p+3, p+4);
+  bool ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4);
 
   printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
 
index dbc5fa4..0eef8c2 100644 (file)
  * Google Author(s): Garret Rieger
  */
 
-#include "hb-private.hh"
-
+#include "hb.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
 
-void
+static void
 test (hb_codepoint_t cp, unsigned int bit)
 {
-  if (OT::hb_get_unicode_range_bit (cp) != bit)
+  if (OT::_hb_ot_os2_get_unicode_range_bit (cp) != bit)
   {
     fprintf (stderr, "got incorrect bit (%d) for cp 0x%X. Should have been %d.",
-             OT::hb_get_unicode_range_bit (cp),
+             OT::_hb_ot_os2_get_unicode_range_bit (cp),
              cp,
              bit);
     abort();
   }
 }
 
-void
-test_get_unicode_range_bit (void)
+static void
+test_get_unicode_range_bit ()
 {
   test (0x0000, 0);
   test (0x0042, 0);
@@ -60,7 +59,7 @@ test_get_unicode_range_bit (void)
 }
 
 int
-main (void)
+main ()
 {
   test_get_unicode_range_bit ();
   return 0;
index 1836d72..268f7db 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb.h"
 #include "hb-ot.h"
index cf59e00..f0eace8 100644 (file)
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb.h"
 
index 5a7e405..2416988 100644 (file)
@@ -96,8 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -304,6 +303,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
index b540eb5..0c7337c 100644 (file)
@@ -3,6 +3,8 @@ if (HB_HAVE_GLIB)
   extract_make_variable (TEST_PROGS ${MAKEFILEAM})
 
   list (APPEND TEST_PROGS
+    test-ot-color
+    test-ot-name
     test-ot-tag
     test-c
     test-cplusplus
index 65ceeda..67d66e1 100644 (file)
@@ -9,11 +9,15 @@ MAINTAINERCLEANFILES =
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 EXTRA_DIST += CMakeLists.txt
 
 EXTRA_DIST += fonts
 
+LINK = $(CXXLINK)
+
 if HAVE_GLIB
 AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS)
 LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
@@ -24,15 +28,19 @@ check_PROGRAMS = $(TEST_PROGS)
 noinst_PROGRAMS = $(TEST_PROGS)
 
 TEST_PROGS = \
+       test-aat-layout \
+       test-baseline \
        test-blob \
        test-buffer \
+       test-collect-unicodes \
        test-common \
        test-font \
+       test-map \
        test-object \
+       test-ot-face \
        test-set \
        test-shape \
        test-subset \
-       test-subset-codepoints \
        test-subset-cmap \
        test-subset-glyf \
        test-subset-hdmx \
@@ -40,12 +48,13 @@ TEST_PROGS = \
        test-subset-os2 \
        test-subset-post \
        test-subset-vmtx \
+       test-subset-cff1 \
+       test-subset-cff2 \
        test-unicode \
        test-version \
        $(NULL)
 
 test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
-test_subset_codepoints_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
@@ -53,6 +62,8 @@ test_subset_hmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_os2_LDADD  = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_post_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_vmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_cff1_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_cff2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 
 test_unicode_CPPFLAGS = \
        $(AM_CPPFLAGS) \
@@ -65,13 +76,26 @@ test_unicode_LDADD += $(top_builddir)/src/libharfbuzz-icu.la $(ICU_LIBS)
 endif
 
 
-if HAVE_OT
-
 TEST_PROGS += \
        test-ot-color \
+       test-ot-ligature-carets \
+       test-ot-name \
        test-ot-tag \
+       test-ot-extents-cff \
        $(NULL)
 
+
+if HAVE_PTHREAD
+if HAVE_FREETYPE
+TEST_PROGS += test-multithread
+test_multithread_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(FREETYPE_CFLAGS)
+test_multithread_LDADD = $(LDADD) $(PTHREAD_LIBS) $(FREETYPE_LIBS)
+# The auto-generated link rule somehow includes CFLAGS as well.  Without
+# it, pthread link fails, because, who knows why, $PTHREAD_LIBS is empty.
+test_multithread_LINK = $(LINK) $(PTHREAD_CFLAGS)
+endif
+endif
+
 if HAVE_FREETYPE
 TEST_PROGS += \
        test-ot-math \
@@ -80,7 +104,6 @@ test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
 test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
 endif # HAVE_FREETYPE
 
-endif # HAVE_OT
 
 # Tests for header compilation
 TEST_PROGS += \
@@ -131,9 +154,9 @@ check-gtester:
 
 # Check tests under valgrind.  Saves log to log-valgrind.txt
 VALGRIND_FLAGS = \
-       --tool=memcheck --suppressions=$(srcdir)/.valgrind-suppressions \
+       --tool=memcheck \
        --track-origins=yes \
-       --leak-check=yes
+       --leak-check=yes \
        $(EXTRA_VALGRIND_FLAGS)
 #      Can't do for now: --show-reachable=yes
 CLEANFILES +=  log-valgrind.txt
@@ -152,13 +175,18 @@ symbols-tested.txt: $(TEST_PROGS)
        $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
        | grep ' U hb_' | sed 's/.* U hb_/hb_/' \
        | sort | uniq > $@.tmp && mv $@.tmp $@
+symbols-tested-or-deprecated.txt: symbols-tested.txt $(top_builddir)/src/harfbuzz-deprecated-symbols.txt
+       $(AM_V_GEN)cat $^ | sort | uniq > $@.tmp; mv $@.tmp $@
 symbols-exported.txt: $(top_builddir)/src/.libs/libharfbuzz.so
        $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
        | grep ' T ' | sed 's/.* T //' | grep -v '^\(_init\|_fini\)$$' \
        | sort | uniq > $@.tmp && mv $@.tmp $@
-symbols-untested.txt: symbols-tested.txt symbols-exported.txt
+symbols-untested.txt: symbols-tested-or-deprecated.txt symbols-exported.txt
        $(AM_V_GEN)diff $^ > $@.tmp; mv $@.tmp $@
-CLEANFILES += symbols-tested.txt symbols-exported.txt symbols-untested.txt
+CLEANFILES += symbols-tested.txt \
+       symbols-exported.txt \
+       symbols-untested.txt \
+       symbols-tested-or-deprecated.txt
 check-symbols: symbols-untested.txt
        @! cat $^ | grep .
 
index c08ad51..b317eb5 100644 (file)
@@ -95,14 +95,10 @@ host_triplet = @host@
 @HAVE_GLIB_TRUE@noinst_PROGRAMS = $(am__EXEEXT_4)
 @HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_2 = $(ICU_CFLAGS)
 @HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_3 = $(top_builddir)/src/libharfbuzz-icu.la $(ICU_LIBS)
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__append_4 = \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ test-ot-color \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ test-ot-tag \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ $(NULL)
-
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__append_5 = \
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@     test-ot-math \
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@     $(NULL)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@am__append_4 = test-multithread
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__append_5 = \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   test-ot-math \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   $(NULL)
 
 @HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_6 = $(ICU_CFLAGS)
 @HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_7 = $(ICU_CFLAGS)
@@ -111,7 +107,8 @@ host_triplet = @host@
 @HAVE_GLIB_TRUE@TESTS = $(am__EXEEXT_4)
 #      Can't do for now: --show-reachable=yes
 @HAVE_GLIB_TRUE@am__append_10 = log-valgrind.txt symbols-tested.txt \
-@HAVE_GLIB_TRUE@       symbols-exported.txt symbols-untested.txt
+@HAVE_GLIB_TRUE@       symbols-exported.txt symbols-untested.txt \
+@HAVE_GLIB_TRUE@       symbols-tested-or-deprecated.txt
 subdir = test/api
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
@@ -119,8 +116,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -129,16 +125,18 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 am__EXEEXT_1 =
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__EXEEXT_2 = test-ot-color$(EXEEXT) \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ test-ot-tag$(EXEEXT) \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ $(am__EXEEXT_1)
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__EXEEXT_3 = test-ot-math$(EXEEXT) \
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@     $(am__EXEEXT_1)
-@HAVE_GLIB_TRUE@am__EXEEXT_4 = test-blob$(EXEEXT) test-buffer$(EXEEXT) \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@am__EXEEXT_2 = test-multithread$(EXEEXT)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__EXEEXT_3 =  \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   test-ot-math$(EXEEXT) \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   $(am__EXEEXT_1)
+@HAVE_GLIB_TRUE@am__EXEEXT_4 = test-aat-layout$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-baseline$(EXEEXT) test-blob$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-buffer$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-collect-unicodes$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-common$(EXEEXT) test-font$(EXEEXT) \
-@HAVE_GLIB_TRUE@       test-object$(EXEEXT) test-set$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-map$(EXEEXT) test-object$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-ot-face$(EXEEXT) test-set$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-shape$(EXEEXT) test-subset$(EXEEXT) \
-@HAVE_GLIB_TRUE@       test-subset-codepoints$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-subset-cmap$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-subset-glyf$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-subset-hdmx$(EXEEXT) \
@@ -146,22 +144,40 @@ am__EXEEXT_1 =
 @HAVE_GLIB_TRUE@       test-subset-os2$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-subset-post$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-subset-vmtx$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-subset-cff1$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-subset-cff2$(EXEEXT) \
 @HAVE_GLIB_TRUE@       test-unicode$(EXEEXT) test-version$(EXEEXT) \
-@HAVE_GLIB_TRUE@       $(am__EXEEXT_1) $(am__EXEEXT_2) \
-@HAVE_GLIB_TRUE@       $(am__EXEEXT_3) test-c$(EXEEXT) \
-@HAVE_GLIB_TRUE@       test-cplusplus$(EXEEXT) $(am__EXEEXT_1)
+@HAVE_GLIB_TRUE@       $(am__EXEEXT_1) test-ot-color$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-ot-ligature-carets$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-ot-name$(EXEEXT) test-ot-tag$(EXEEXT) \
+@HAVE_GLIB_TRUE@       test-ot-extents-cff$(EXEEXT) $(am__EXEEXT_1) \
+@HAVE_GLIB_TRUE@       $(am__EXEEXT_2) $(am__EXEEXT_3) \
+@HAVE_GLIB_TRUE@       test-c$(EXEEXT) test-cplusplus$(EXEEXT) \
+@HAVE_GLIB_TRUE@       $(am__EXEEXT_1)
 PROGRAMS = $(noinst_PROGRAMS)
-test_blob_SOURCES = test-blob.c
-test_blob_OBJECTS = test-blob.$(OBJEXT)
-test_blob_LDADD = $(LDADD)
+test_aat_layout_SOURCES = test-aat-layout.c
+test_aat_layout_OBJECTS = test-aat-layout.$(OBJEXT)
+test_aat_layout_LDADD = $(LDADD)
 am__DEPENDENCIES_1 =
-@HAVE_GLIB_TRUE@test_blob_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@test_aat_layout_DEPENDENCIES =  \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
 @HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
+test_baseline_SOURCES = test-baseline.c
+test_baseline_OBJECTS = test-baseline.$(OBJEXT)
+test_baseline_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_baseline_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_blob_SOURCES = test-blob.c
+test_blob_OBJECTS = test-blob.$(OBJEXT)
+test_blob_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_blob_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
 test_buffer_SOURCES = test-buffer.c
 test_buffer_OBJECTS = test-buffer.$(OBJEXT)
 test_buffer_LDADD = $(LDADD)
@@ -174,6 +190,12 @@ test_c_LDADD = $(LDADD)
 @HAVE_GLIB_TRUE@test_c_DEPENDENCIES =  \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
 @HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_collect_unicodes_SOURCES = test-collect-unicodes.c
+test_collect_unicodes_OBJECTS = test-collect-unicodes.$(OBJEXT)
+test_collect_unicodes_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_collect_unicodes_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
 test_common_SOURCES = test-common.c
 test_common_OBJECTS = test-common.$(OBJEXT)
 test_common_LDADD = $(LDADD)
@@ -194,6 +216,21 @@ test_font_LDADD = $(LDADD)
 @HAVE_GLIB_TRUE@test_font_DEPENDENCIES =  \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
 @HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_map_SOURCES = test-map.c
+test_map_OBJECTS = test-map.$(OBJEXT)
+test_map_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_map_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_multithread_SOURCES = test-multithread.c
+test_multithread_OBJECTS =  \
+       test_multithread-test-multithread.$(OBJEXT)
+@HAVE_GLIB_TRUE@am__DEPENDENCIES_2 =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@test_multithread_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@        $(am__DEPENDENCIES_1) \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@        $(am__DEPENDENCIES_1)
 test_object_SOURCES = test-object.c
 test_object_OBJECTS = test-object.$(OBJEXT)
 test_object_LDADD = $(LDADD)
@@ -206,13 +243,35 @@ test_ot_color_LDADD = $(LDADD)
 @HAVE_GLIB_TRUE@test_ot_color_DEPENDENCIES =  \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
 @HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_ot_extents_cff_SOURCES = test-ot-extents-cff.c
+test_ot_extents_cff_OBJECTS = test-ot-extents-cff.$(OBJEXT)
+test_ot_extents_cff_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_ot_extents_cff_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_ot_face_SOURCES = test-ot-face.c
+test_ot_face_OBJECTS = test-ot-face.$(OBJEXT)
+test_ot_face_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_ot_face_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
+test_ot_ligature_carets_SOURCES = test-ot-ligature-carets.c
+test_ot_ligature_carets_OBJECTS = test-ot-ligature-carets.$(OBJEXT)
+test_ot_ligature_carets_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_ot_ligature_carets_DEPENDENCIES =  \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
+@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
 test_ot_math_SOURCES = test-ot-math.c
 test_ot_math_OBJECTS = test_ot_math-test-ot-math.$(OBJEXT)
-@HAVE_GLIB_TRUE@am__DEPENDENCIES_2 =  \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@test_ot_math_DEPENDENCIES =  \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   $(am__DEPENDENCIES_2) \
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@   $(am__DEPENDENCIES_1)
+test_ot_name_SOURCES = test-ot-name.c
+test_ot_name_OBJECTS = test-ot-name.$(OBJEXT)
+test_ot_name_LDADD = $(LDADD)
+@HAVE_GLIB_TRUE@test_ot_name_DEPENDENCIES =  \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz.la \
 @HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_1)
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@test_ot_math_DEPENDENCIES = $(am__DEPENDENCIES_2) \
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@     $(am__DEPENDENCIES_1)
 test_ot_tag_SOURCES = test-ot-tag.c
 test_ot_tag_OBJECTS = test-ot-tag.$(OBJEXT)
 test_ot_tag_LDADD = $(LDADD)
@@ -235,15 +294,18 @@ test_subset_SOURCES = test-subset.c
 test_subset_OBJECTS = test-subset.$(OBJEXT)
 @HAVE_GLIB_TRUE@test_subset_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_cff1_SOURCES = test-subset-cff1.c
+test_subset_cff1_OBJECTS = test-subset-cff1.$(OBJEXT)
+@HAVE_GLIB_TRUE@test_subset_cff1_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_cff2_SOURCES = test-subset-cff2.c
+test_subset_cff2_OBJECTS = test-subset-cff2.$(OBJEXT)
+@HAVE_GLIB_TRUE@test_subset_cff2_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cmap_SOURCES = test-subset-cmap.c
 test_subset_cmap_OBJECTS = test-subset-cmap.$(OBJEXT)
 @HAVE_GLIB_TRUE@test_subset_cmap_DEPENDENCIES = $(am__DEPENDENCIES_2) \
 @HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
-test_subset_codepoints_SOURCES = test-subset-codepoints.c
-test_subset_codepoints_OBJECTS = test-subset-codepoints.$(OBJEXT)
-@HAVE_GLIB_TRUE@test_subset_codepoints_DEPENDENCIES =  \
-@HAVE_GLIB_TRUE@       $(am__DEPENDENCIES_2) \
-@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_glyf_SOURCES = test-subset-glyf.c
 test_subset_glyf_OBJECTS = test-subset-glyf.$(OBJEXT)
 @HAVE_GLIB_TRUE@test_subset_glyf_DEPENDENCIES = $(am__DEPENDENCIES_2) \
@@ -307,9 +369,6 @@ am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
 am__v_CC_0 = @echo "  CC      " $@;
 am__v_CC_1 = 
 CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
 AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
@@ -332,20 +391,28 @@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
 am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
 am__v_CXXLD_0 = @echo "  CXXLD   " $@;
 am__v_CXXLD_1 = 
-SOURCES = test-blob.c test-buffer.c test-c.c test-common.c \
-       $(test_cplusplus_SOURCES) test-font.c test-object.c \
-       test-ot-color.c test-ot-math.c test-ot-tag.c test-set.c \
-       test-shape.c test-subset.c test-subset-cmap.c \
-       test-subset-codepoints.c test-subset-glyf.c test-subset-hdmx.c \
-       test-subset-hmtx.c test-subset-os2.c test-subset-post.c \
-       test-subset-vmtx.c test-unicode.c test-version.c
-DIST_SOURCES = test-blob.c test-buffer.c test-c.c test-common.c \
-       $(am__test_cplusplus_SOURCES_DIST) test-font.c test-object.c \
-       test-ot-color.c test-ot-math.c test-ot-tag.c test-set.c \
-       test-shape.c test-subset.c test-subset-cmap.c \
-       test-subset-codepoints.c test-subset-glyf.c test-subset-hdmx.c \
-       test-subset-hmtx.c test-subset-os2.c test-subset-post.c \
-       test-subset-vmtx.c test-unicode.c test-version.c
+SOURCES = test-aat-layout.c test-baseline.c test-blob.c test-buffer.c \
+       test-c.c test-collect-unicodes.c test-common.c \
+       $(test_cplusplus_SOURCES) test-font.c test-map.c \
+       test-multithread.c test-object.c test-ot-color.c \
+       test-ot-extents-cff.c test-ot-face.c test-ot-ligature-carets.c \
+       test-ot-math.c test-ot-name.c test-ot-tag.c test-set.c \
+       test-shape.c test-subset.c test-subset-cff1.c \
+       test-subset-cff2.c test-subset-cmap.c test-subset-glyf.c \
+       test-subset-hdmx.c test-subset-hmtx.c test-subset-os2.c \
+       test-subset-post.c test-subset-vmtx.c test-unicode.c \
+       test-version.c
+DIST_SOURCES = test-aat-layout.c test-baseline.c test-blob.c \
+       test-buffer.c test-c.c test-collect-unicodes.c test-common.c \
+       $(am__test_cplusplus_SOURCES_DIST) test-font.c test-map.c \
+       test-multithread.c test-object.c test-ot-color.c \
+       test-ot-extents-cff.c test-ot-face.c test-ot-ligature-carets.c \
+       test-ot-math.c test-ot-name.c test-ot-tag.c test-set.c \
+       test-shape.c test-subset.c test-subset-cff1.c \
+       test-subset-cff2.c test-subset-cmap.c test-subset-glyf.c \
+       test-subset-hdmx.c test-subset-hmtx.c test-subset-os2.c \
+       test-subset-post.c test-subset-vmtx.c test-unicode.c \
+       test-version.c
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -694,6 +761,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -767,21 +836,25 @@ EXTRA_DIST = CMakeLists.txt fonts $(am__append_1)
 CLEANFILES = $(am__append_10)
 DISTCLEANFILES = 
 MAINTAINERCLEANFILES = 
+LINK = $(CXXLINK)
 @HAVE_GLIB_TRUE@AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS)
 @HAVE_GLIB_TRUE@LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
 
 # Tests for header compilation
-@HAVE_GLIB_TRUE@TEST_PROGS = test-blob test-buffer test-common \
-@HAVE_GLIB_TRUE@       test-font test-object test-set test-shape \
-@HAVE_GLIB_TRUE@       test-subset test-subset-codepoints \
+@HAVE_GLIB_TRUE@TEST_PROGS = test-aat-layout test-baseline test-blob \
+@HAVE_GLIB_TRUE@       test-buffer test-collect-unicodes test-common \
+@HAVE_GLIB_TRUE@       test-font test-map test-object test-ot-face \
+@HAVE_GLIB_TRUE@       test-set test-shape test-subset \
 @HAVE_GLIB_TRUE@       test-subset-cmap test-subset-glyf \
 @HAVE_GLIB_TRUE@       test-subset-hdmx test-subset-hmtx \
 @HAVE_GLIB_TRUE@       test-subset-os2 test-subset-post \
-@HAVE_GLIB_TRUE@       test-subset-vmtx test-unicode test-version \
+@HAVE_GLIB_TRUE@       test-subset-vmtx test-subset-cff1 \
+@HAVE_GLIB_TRUE@       test-subset-cff2 test-unicode test-version \
+@HAVE_GLIB_TRUE@       $(NULL) test-ot-color test-ot-ligature-carets \
+@HAVE_GLIB_TRUE@       test-ot-name test-ot-tag test-ot-extents-cff \
 @HAVE_GLIB_TRUE@       $(NULL) $(am__append_4) $(am__append_5) test-c \
 @HAVE_GLIB_TRUE@       test-cplusplus $(NULL)
 @HAVE_GLIB_TRUE@test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
-@HAVE_GLIB_TRUE@test_subset_codepoints_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
@@ -789,11 +862,18 @@ MAINTAINERCLEANFILES =
 @HAVE_GLIB_TRUE@test_subset_os2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_subset_post_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_subset_vmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+@HAVE_GLIB_TRUE@test_subset_cff1_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+@HAVE_GLIB_TRUE@test_subset_cff2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 @HAVE_GLIB_TRUE@test_unicode_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) \
 @HAVE_GLIB_TRUE@       $(NULL) $(am__append_2)
 @HAVE_GLIB_TRUE@test_unicode_LDADD = $(LDADD) $(am__append_3)
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
-@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@test_multithread_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(FREETYPE_CFLAGS)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@test_multithread_LDADD = $(LDADD) $(PTHREAD_LIBS) $(FREETYPE_LIBS)
+# The auto-generated link rule somehow includes CFLAGS as well.  Without
+# it, pthread link fails, because, who knows why, $PTHREAD_LIBS is empty.
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@@HAVE_PTHREAD_TRUE@test_multithread_LINK = $(LINK) $(PTHREAD_CFLAGS)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
+@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
 @HAVE_GLIB_TRUE@test_cplusplus_SOURCES = test-cplusplus.cc
 @HAVE_GLIB_TRUE@test_c_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_6) \
 @HAVE_GLIB_TRUE@       $(am__append_8)
@@ -815,9 +895,10 @@ MAINTAINERCLEANFILES =
 
 # Check tests under valgrind.  Saves log to log-valgrind.txt
 @HAVE_GLIB_TRUE@VALGRIND_FLAGS = \
-@HAVE_GLIB_TRUE@       --tool=memcheck --suppressions=$(srcdir)/.valgrind-suppressions \
+@HAVE_GLIB_TRUE@       --tool=memcheck \
 @HAVE_GLIB_TRUE@       --track-origins=yes \
-@HAVE_GLIB_TRUE@       --leak-check=yes
+@HAVE_GLIB_TRUE@       --leak-check=yes \
+@HAVE_GLIB_TRUE@       $(EXTRA_VALGRIND_FLAGS)
 
 @HAVE_GLIB_TRUE@valgrind_verbose = $(valgrind_verbose_@AM_V@)
 @HAVE_GLIB_TRUE@valgrind_verbose_ = $(valgrind_verbose_@AM_DEFAULT_V@)
@@ -876,6 +957,14 @@ clean-noinstPROGRAMS:
        echo " rm -f" $$list; \
        rm -f $$list
 
+test-aat-layout$(EXEEXT): $(test_aat_layout_OBJECTS) $(test_aat_layout_DEPENDENCIES) $(EXTRA_test_aat_layout_DEPENDENCIES) 
+       @rm -f test-aat-layout$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_aat_layout_OBJECTS) $(test_aat_layout_LDADD) $(LIBS)
+
+test-baseline$(EXEEXT): $(test_baseline_OBJECTS) $(test_baseline_DEPENDENCIES) $(EXTRA_test_baseline_DEPENDENCIES) 
+       @rm -f test-baseline$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_baseline_OBJECTS) $(test_baseline_LDADD) $(LIBS)
+
 test-blob$(EXEEXT): $(test_blob_OBJECTS) $(test_blob_DEPENDENCIES) $(EXTRA_test_blob_DEPENDENCIES) 
        @rm -f test-blob$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_blob_OBJECTS) $(test_blob_LDADD) $(LIBS)
@@ -888,6 +977,10 @@ test-c$(EXEEXT): $(test_c_OBJECTS) $(test_c_DEPENDENCIES) $(EXTRA_test_c_DEPENDE
        @rm -f test-c$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_c_OBJECTS) $(test_c_LDADD) $(LIBS)
 
+test-collect-unicodes$(EXEEXT): $(test_collect_unicodes_OBJECTS) $(test_collect_unicodes_DEPENDENCIES) $(EXTRA_test_collect_unicodes_DEPENDENCIES) 
+       @rm -f test-collect-unicodes$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_collect_unicodes_OBJECTS) $(test_collect_unicodes_LDADD) $(LIBS)
+
 test-common$(EXEEXT): $(test_common_OBJECTS) $(test_common_DEPENDENCIES) $(EXTRA_test_common_DEPENDENCIES) 
        @rm -f test-common$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_common_OBJECTS) $(test_common_LDADD) $(LIBS)
@@ -900,6 +993,14 @@ test-font$(EXEEXT): $(test_font_OBJECTS) $(test_font_DEPENDENCIES) $(EXTRA_test_
        @rm -f test-font$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_font_OBJECTS) $(test_font_LDADD) $(LIBS)
 
+test-map$(EXEEXT): $(test_map_OBJECTS) $(test_map_DEPENDENCIES) $(EXTRA_test_map_DEPENDENCIES) 
+       @rm -f test-map$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_map_OBJECTS) $(test_map_LDADD) $(LIBS)
+
+test-multithread$(EXEEXT): $(test_multithread_OBJECTS) $(test_multithread_DEPENDENCIES) $(EXTRA_test_multithread_DEPENDENCIES) 
+       @rm -f test-multithread$(EXEEXT)
+       $(AM_V_GEN)$(test_multithread_LINK) $(test_multithread_OBJECTS) $(test_multithread_LDADD) $(LIBS)
+
 test-object$(EXEEXT): $(test_object_OBJECTS) $(test_object_DEPENDENCIES) $(EXTRA_test_object_DEPENDENCIES) 
        @rm -f test-object$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_object_OBJECTS) $(test_object_LDADD) $(LIBS)
@@ -908,10 +1009,26 @@ test-ot-color$(EXEEXT): $(test_ot_color_OBJECTS) $(test_ot_color_DEPENDENCIES) $
        @rm -f test-ot-color$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_ot_color_OBJECTS) $(test_ot_color_LDADD) $(LIBS)
 
+test-ot-extents-cff$(EXEEXT): $(test_ot_extents_cff_OBJECTS) $(test_ot_extents_cff_DEPENDENCIES) $(EXTRA_test_ot_extents_cff_DEPENDENCIES) 
+       @rm -f test-ot-extents-cff$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_ot_extents_cff_OBJECTS) $(test_ot_extents_cff_LDADD) $(LIBS)
+
+test-ot-face$(EXEEXT): $(test_ot_face_OBJECTS) $(test_ot_face_DEPENDENCIES) $(EXTRA_test_ot_face_DEPENDENCIES) 
+       @rm -f test-ot-face$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_ot_face_OBJECTS) $(test_ot_face_LDADD) $(LIBS)
+
+test-ot-ligature-carets$(EXEEXT): $(test_ot_ligature_carets_OBJECTS) $(test_ot_ligature_carets_DEPENDENCIES) $(EXTRA_test_ot_ligature_carets_DEPENDENCIES) 
+       @rm -f test-ot-ligature-carets$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_ot_ligature_carets_OBJECTS) $(test_ot_ligature_carets_LDADD) $(LIBS)
+
 test-ot-math$(EXEEXT): $(test_ot_math_OBJECTS) $(test_ot_math_DEPENDENCIES) $(EXTRA_test_ot_math_DEPENDENCIES) 
        @rm -f test-ot-math$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_ot_math_OBJECTS) $(test_ot_math_LDADD) $(LIBS)
 
+test-ot-name$(EXEEXT): $(test_ot_name_OBJECTS) $(test_ot_name_DEPENDENCIES) $(EXTRA_test_ot_name_DEPENDENCIES) 
+       @rm -f test-ot-name$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_ot_name_OBJECTS) $(test_ot_name_LDADD) $(LIBS)
+
 test-ot-tag$(EXEEXT): $(test_ot_tag_OBJECTS) $(test_ot_tag_DEPENDENCIES) $(EXTRA_test_ot_tag_DEPENDENCIES) 
        @rm -f test-ot-tag$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_ot_tag_OBJECTS) $(test_ot_tag_LDADD) $(LIBS)
@@ -928,14 +1045,18 @@ test-subset$(EXEEXT): $(test_subset_OBJECTS) $(test_subset_DEPENDENCIES) $(EXTRA
        @rm -f test-subset$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_subset_OBJECTS) $(test_subset_LDADD) $(LIBS)
 
+test-subset-cff1$(EXEEXT): $(test_subset_cff1_OBJECTS) $(test_subset_cff1_DEPENDENCIES) $(EXTRA_test_subset_cff1_DEPENDENCIES) 
+       @rm -f test-subset-cff1$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_subset_cff1_OBJECTS) $(test_subset_cff1_LDADD) $(LIBS)
+
+test-subset-cff2$(EXEEXT): $(test_subset_cff2_OBJECTS) $(test_subset_cff2_DEPENDENCIES) $(EXTRA_test_subset_cff2_DEPENDENCIES) 
+       @rm -f test-subset-cff2$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_subset_cff2_OBJECTS) $(test_subset_cff2_LDADD) $(LIBS)
+
 test-subset-cmap$(EXEEXT): $(test_subset_cmap_OBJECTS) $(test_subset_cmap_DEPENDENCIES) $(EXTRA_test_subset_cmap_DEPENDENCIES) 
        @rm -f test-subset-cmap$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_subset_cmap_OBJECTS) $(test_subset_cmap_LDADD) $(LIBS)
 
-test-subset-codepoints$(EXEEXT): $(test_subset_codepoints_OBJECTS) $(test_subset_codepoints_DEPENDENCIES) $(EXTRA_test_subset_codepoints_DEPENDENCIES) 
-       @rm -f test-subset-codepoints$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(test_subset_codepoints_OBJECTS) $(test_subset_codepoints_LDADD) $(LIBS)
-
 test-subset-glyf$(EXEEXT): $(test_subset_glyf_OBJECTS) $(test_subset_glyf_DEPENDENCIES) $(EXTRA_test_subset_glyf_DEPENDENCIES) 
        @rm -f test-subset-glyf$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(test_subset_glyf_OBJECTS) $(test_subset_glyf_LDADD) $(LIBS)
@@ -974,17 +1095,26 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-aat-layout.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-baseline.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-blob.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-buffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-collect-unicodes.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-font.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-map.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-object.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-color.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-extents-cff.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-face.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-ligature-carets.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-name.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-tag.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-set.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-shape.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-cff1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-cff2.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-cmap.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-codepoints.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-glyf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-hdmx.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-subset-hmtx.Po@am__quote@
@@ -995,6 +1125,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-version.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_c-test-c.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cplusplus-test-cplusplus.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_multithread-test-multithread.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ot_math-test-ot-math.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_unicode-test-unicode.Po@am__quote@
 
@@ -1033,6 +1164,20 @@ test_c-test-c.obj: test-c.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_c_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_c-test-c.obj `if test -f 'test-c.c'; then $(CYGPATH_W) 'test-c.c'; else $(CYGPATH_W) '$(srcdir)/test-c.c'; fi`
 
+test_multithread-test-multithread.o: test-multithread.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_multithread_CFLAGS) $(CFLAGS) -MT test_multithread-test-multithread.o -MD -MP -MF $(DEPDIR)/test_multithread-test-multithread.Tpo -c -o test_multithread-test-multithread.o `test -f 'test-multithread.c' || echo '$(srcdir)/'`test-multithread.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/test_multithread-test-multithread.Tpo $(DEPDIR)/test_multithread-test-multithread.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='test-multithread.c' object='test_multithread-test-multithread.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_multithread_CFLAGS) $(CFLAGS) -c -o test_multithread-test-multithread.o `test -f 'test-multithread.c' || echo '$(srcdir)/'`test-multithread.c
+
+test_multithread-test-multithread.obj: test-multithread.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_multithread_CFLAGS) $(CFLAGS) -MT test_multithread-test-multithread.obj -MD -MP -MF $(DEPDIR)/test_multithread-test-multithread.Tpo -c -o test_multithread-test-multithread.obj `if test -f 'test-multithread.c'; then $(CYGPATH_W) 'test-multithread.c'; else $(CYGPATH_W) '$(srcdir)/test-multithread.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/test_multithread-test-multithread.Tpo $(DEPDIR)/test_multithread-test-multithread.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='test-multithread.c' object='test_multithread-test-multithread.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_multithread_CFLAGS) $(CFLAGS) -c -o test_multithread-test-multithread.obj `if test -f 'test-multithread.c'; then $(CYGPATH_W) 'test-multithread.c'; else $(CYGPATH_W) '$(srcdir)/test-multithread.c'; fi`
+
 test_ot_math-test-ot-math.o: test-ot-math.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ot_math_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_ot_math-test-ot-math.o -MD -MP -MF $(DEPDIR)/test_ot_math-test-ot-math.Tpo -c -o test_ot_math-test-ot-math.o `test -f 'test-ot-math.c' || echo '$(srcdir)/'`test-ot-math.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/test_ot_math-test-ot-math.Tpo $(DEPDIR)/test_ot_math-test-ot-math.Po
@@ -1295,6 +1440,20 @@ recheck: all $(check_PROGRAMS)
                am__force_recheck=am--force-recheck \
                TEST_LOGS="$$log_list"; \
        exit $$?
+test-aat-layout.log: test-aat-layout$(EXEEXT)
+       @p='test-aat-layout$(EXEEXT)'; \
+       b='test-aat-layout'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-baseline.log: test-baseline$(EXEEXT)
+       @p='test-baseline$(EXEEXT)'; \
+       b='test-baseline'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-blob.log: test-blob$(EXEEXT)
        @p='test-blob$(EXEEXT)'; \
        b='test-blob'; \
@@ -1309,6 +1468,13 @@ test-buffer.log: test-buffer$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-collect-unicodes.log: test-collect-unicodes$(EXEEXT)
+       @p='test-collect-unicodes$(EXEEXT)'; \
+       b='test-collect-unicodes'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-common.log: test-common$(EXEEXT)
        @p='test-common$(EXEEXT)'; \
        b='test-common'; \
@@ -1323,6 +1489,13 @@ test-font.log: test-font$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-map.log: test-map$(EXEEXT)
+       @p='test-map$(EXEEXT)'; \
+       b='test-map'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-object.log: test-object$(EXEEXT)
        @p='test-object$(EXEEXT)'; \
        b='test-object'; \
@@ -1330,6 +1503,13 @@ test-object.log: test-object$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-ot-face.log: test-ot-face$(EXEEXT)
+       @p='test-ot-face$(EXEEXT)'; \
+       b='test-ot-face'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-set.log: test-set$(EXEEXT)
        @p='test-set$(EXEEXT)'; \
        b='test-set'; \
@@ -1351,13 +1531,6 @@ test-subset.log: test-subset$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
-test-subset-codepoints.log: test-subset-codepoints$(EXEEXT)
-       @p='test-subset-codepoints$(EXEEXT)'; \
-       b='test-subset-codepoints'; \
-       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
-       --log-file $$b.log --trs-file $$b.trs \
-       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
-       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-subset-cmap.log: test-subset-cmap$(EXEEXT)
        @p='test-subset-cmap$(EXEEXT)'; \
        b='test-subset-cmap'; \
@@ -1407,6 +1580,20 @@ test-subset-vmtx.log: test-subset-vmtx$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-subset-cff1.log: test-subset-cff1$(EXEEXT)
+       @p='test-subset-cff1$(EXEEXT)'; \
+       b='test-subset-cff1'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-subset-cff2.log: test-subset-cff2$(EXEEXT)
+       @p='test-subset-cff2$(EXEEXT)'; \
+       b='test-subset-cff2'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-unicode.log: test-unicode$(EXEEXT)
        @p='test-unicode$(EXEEXT)'; \
        b='test-unicode'; \
@@ -1428,6 +1615,20 @@ test-ot-color.log: test-ot-color$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-ot-ligature-carets.log: test-ot-ligature-carets$(EXEEXT)
+       @p='test-ot-ligature-carets$(EXEEXT)'; \
+       b='test-ot-ligature-carets'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-ot-name.log: test-ot-name$(EXEEXT)
+       @p='test-ot-name$(EXEEXT)'; \
+       b='test-ot-name'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-ot-tag.log: test-ot-tag$(EXEEXT)
        @p='test-ot-tag$(EXEEXT)'; \
        b='test-ot-tag'; \
@@ -1435,6 +1636,20 @@ test-ot-tag.log: test-ot-tag$(EXEEXT)
        --log-file $$b.log --trs-file $$b.trs \
        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
        "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-ot-extents-cff.log: test-ot-extents-cff$(EXEEXT)
+       @p='test-ot-extents-cff$(EXEEXT)'; \
+       b='test-ot-extents-cff'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-multithread.log: test-multithread$(EXEEXT)
+       @p='test-multithread$(EXEEXT)'; \
+       b='test-multithread'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
 test-ot-math.log: test-ot-math$(EXEEXT)
        @p='test-ot-math$(EXEEXT)'; \
        b='test-ot-math'; \
@@ -1637,6 +1852,8 @@ uninstall-am:
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 # check-tool: Run tests under $(TOOL)
 @HAVE_GLIB_TRUE@check-tool:
@@ -1650,7 +1867,6 @@ lib:
 @HAVE_GLIB_TRUE@       env $(TOOL)'
 @HAVE_GLIB_TRUE@check-gtester:
 @HAVE_GLIB_TRUE@       $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool-raw TOOL="$(GTESTER) --verbose --keep-going"
-@HAVE_GLIB_TRUE@       $(EXTRA_VALGRIND_FLAGS)
 # TODO: The following check does not fail if valgrind finds error.  It should.
 @HAVE_GLIB_TRUE@check-valgrind:
 @HAVE_GLIB_TRUE@       $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool TOOL="valgrind $(VALGRIND_FLAGS)" \
@@ -1661,11 +1877,13 @@ lib:
 @HAVE_GLIB_TRUE@       $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
 @HAVE_GLIB_TRUE@       | grep ' U hb_' | sed 's/.* U hb_/hb_/' \
 @HAVE_GLIB_TRUE@       | sort | uniq > $@.tmp && mv $@.tmp $@
+@HAVE_GLIB_TRUE@symbols-tested-or-deprecated.txt: symbols-tested.txt $(top_builddir)/src/harfbuzz-deprecated-symbols.txt
+@HAVE_GLIB_TRUE@       $(AM_V_GEN)cat $^ | sort | uniq > $@.tmp; mv $@.tmp $@
 @HAVE_GLIB_TRUE@symbols-exported.txt: $(top_builddir)/src/.libs/libharfbuzz.so
 @HAVE_GLIB_TRUE@       $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
 @HAVE_GLIB_TRUE@       | grep ' T ' | sed 's/.* T //' | grep -v '^\(_init\|_fini\)$$' \
 @HAVE_GLIB_TRUE@       | sort | uniq > $@.tmp && mv $@.tmp $@
-@HAVE_GLIB_TRUE@symbols-untested.txt: symbols-tested.txt symbols-exported.txt
+@HAVE_GLIB_TRUE@symbols-untested.txt: symbols-tested-or-deprecated.txt symbols-exported.txt
 @HAVE_GLIB_TRUE@       $(AM_V_GEN)diff $^ > $@.tmp; mv $@.tmp $@
 @HAVE_GLIB_TRUE@check-symbols: symbols-untested.txt
 @HAVE_GLIB_TRUE@       @! cat $^ | grep .
diff --git a/test/api/fonts/AdobeVFPrototype.abc.otf b/test/api/fonts/AdobeVFPrototype.abc.otf
new file mode 100644 (file)
index 0000000..cc47708
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype.abc.otf differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nohints.otf b/test/api/fonts/AdobeVFPrototype.ac.nohints.otf
new file mode 100644 (file)
index 0000000..935bdbf
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype.ac.nohints.otf differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf
new file mode 100644 (file)
index 0000000..85f6cf6
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf
new file mode 100644 (file)
index 0000000..ad4d53b
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype.ac.nosubrs.otf differ
diff --git a/test/api/fonts/AdobeVFPrototype.ac.otf b/test/api/fonts/AdobeVFPrototype.ac.otf
new file mode 100644 (file)
index 0000000..beab7d5
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype.ac.otf differ
diff --git a/test/api/fonts/AdobeVFPrototype_vsindex.otf b/test/api/fonts/AdobeVFPrototype_vsindex.otf
new file mode 100644 (file)
index 0000000..3697b46
Binary files /dev/null and b/test/api/fonts/AdobeVFPrototype_vsindex.otf differ
diff --git a/test/api/fonts/MathTestFontFull.ttx b/test/api/fonts/MathTestFontFull.ttx
deleted file mode 100644 (file)
index 1d1aa53..0000000
+++ /dev/null
@@ -1,6578 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ttFont sfntVersion="OTTO" ttLibVersion="3.0">
-
-  <GlyphOrder>
-    <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
-    <GlyphID id="0" name=".notdef"/>
-    <GlyphID id="1" name="space"/>
-    <GlyphID id="2" name="A"/>
-    <GlyphID id="3" name="B"/>
-    <GlyphID id="4" name="C"/>
-    <GlyphID id="5" name="D"/>
-    <GlyphID id="6" name="E"/>
-    <GlyphID id="7" name="F"/>
-    <GlyphID id="8" name="G"/>
-    <GlyphID id="9" name="H"/>
-    <GlyphID id="10" name="I"/>
-    <GlyphID id="11" name="J"/>
-    <GlyphID id="12" name="K"/>
-    <GlyphID id="13" name="L"/>
-    <GlyphID id="14" name="M"/>
-    <GlyphID id="15" name="N"/>
-    <GlyphID id="16" name="O"/>
-    <GlyphID id="17" name="P"/>
-    <GlyphID id="18" name="Q"/>
-    <GlyphID id="19" name="R"/>
-    <GlyphID id="20" name="S"/>
-    <GlyphID id="21" name="T"/>
-    <GlyphID id="22" name="U"/>
-    <GlyphID id="23" name="V"/>
-    <GlyphID id="24" name="W"/>
-    <GlyphID id="25" name="X"/>
-    <GlyphID id="26" name="Y"/>
-    <GlyphID id="27" name="Z"/>
-    <GlyphID id="28" name="underscore"/>
-    <GlyphID id="29" name="braceleft"/>
-    <GlyphID id="30" name="arrowleft"/>
-    <GlyphID id="31" name="arrowup"/>
-    <GlyphID id="32" name="arrowright"/>
-    <GlyphID id="33" name="arrowdown"/>
-    <GlyphID id="34" name="arrowboth"/>
-    <GlyphID id="35" name="arrowupdn"/>
-    <GlyphID id="36" name="uni21A4"/>
-    <GlyphID id="37" name="uni21A5"/>
-    <GlyphID id="38" name="uni21A6"/>
-    <GlyphID id="39" name="uni21A7"/>
-    <GlyphID id="40" name="uni21C7"/>
-    <GlyphID id="41" name="uni21C8"/>
-    <GlyphID id="42" name="uni21C9"/>
-    <GlyphID id="43" name="uni21CA"/>
-    <GlyphID id="44" name="arrowdblleft"/>
-    <GlyphID id="45" name="arrowdblup"/>
-    <GlyphID id="46" name="arrowdblright"/>
-    <GlyphID id="47" name="arrowdbldown"/>
-    <GlyphID id="48" name="arrowdblboth"/>
-    <GlyphID id="49" name="uni21D5"/>
-    <GlyphID id="50" name="uni21E6"/>
-    <GlyphID id="51" name="uni21E7"/>
-    <GlyphID id="52" name="uni21E8"/>
-    <GlyphID id="53" name="uni21E9"/>
-    <GlyphID id="54" name="uni23A7"/>
-    <GlyphID id="55" name="uni23A8"/>
-    <GlyphID id="56" name="uni23A9"/>
-    <GlyphID id="57" name="uni23AA"/>
-    <GlyphID id="58" name="center"/>
-    <GlyphID id="59" name="left"/>
-    <GlyphID id="60" name="right"/>
-    <GlyphID id="61" name="top"/>
-    <GlyphID id="62" name="bottom"/>
-    <GlyphID id="63" name="horizontal"/>
-    <GlyphID id="64" name="vertical"/>
-    <GlyphID id="65" name="uni2190_size2"/>
-    <GlyphID id="66" name="uni2190_size3"/>
-    <GlyphID id="67" name="uni2190_size4"/>
-    <GlyphID id="68" name="uni2191_size2"/>
-    <GlyphID id="69" name="uni2191_size3"/>
-    <GlyphID id="70" name="uni2191_size4"/>
-    <GlyphID id="71" name="uni2191_size5"/>
-    <GlyphID id="72" name="uni2192_size2"/>
-    <GlyphID id="73" name="uni2192_size3"/>
-    <GlyphID id="74" name="uni2192_size4"/>
-    <GlyphID id="75" name="uni2192_size5"/>
-    <GlyphID id="76" name="uni2192_size6"/>
-    <GlyphID id="77" name="uni2193_size2"/>
-    <GlyphID id="78" name="uni2193_size3"/>
-    <GlyphID id="79" name="uni2193_size4"/>
-    <GlyphID id="80" name="uni2193_size5"/>
-    <GlyphID id="81" name="uni2193_size6"/>
-    <GlyphID id="82" name="uni2193_size7"/>
-    <GlyphID id="83" name="uni2195_size2"/>
-    <GlyphID id="84" name="uni21A4_size2"/>
-    <GlyphID id="85" name="uni21A4_size3"/>
-    <GlyphID id="86" name="uni21A5_size2"/>
-    <GlyphID id="87" name="uni21A5_size3"/>
-    <GlyphID id="88" name="uni21A5_size4"/>
-    <GlyphID id="89" name="uni21A6_size2"/>
-    <GlyphID id="90" name="uni21A6_size3"/>
-    <GlyphID id="91" name="uni21A6_size4"/>
-    <GlyphID id="92" name="uni21A6_size5"/>
-    <GlyphID id="93" name="uni21A7_size2"/>
-    <GlyphID id="94" name="uni21A7_size3"/>
-    <GlyphID id="95" name="uni21A7_size4"/>
-    <GlyphID id="96" name="uni21A7_size5"/>
-    <GlyphID id="97" name="uni21A7_size6"/>
-    <GlyphID id="98" name="uni21C7_size2"/>
-    <GlyphID id="99" name="uni21C7_size3"/>
-    <GlyphID id="100" name="uni21C8_size2"/>
-    <GlyphID id="101" name="uni21C8_size3"/>
-    <GlyphID id="102" name="uni21C8_size4"/>
-    <GlyphID id="103" name="uni21C9_size2"/>
-    <GlyphID id="104" name="uni21C9_size3"/>
-    <GlyphID id="105" name="uni21C9_size4"/>
-    <GlyphID id="106" name="uni21C9_size5"/>
-    <GlyphID id="107" name="uni21CA_size2"/>
-    <GlyphID id="108" name="uni21CA_size3"/>
-    <GlyphID id="109" name="uni21CA_size4"/>
-    <GlyphID id="110" name="uni21CA_size5"/>
-    <GlyphID id="111" name="uni21CA_size6"/>
-    <GlyphID id="112" name="uni21D0_size2"/>
-    <GlyphID id="113" name="uni21D0_size3"/>
-    <GlyphID id="114" name="uni21D0_size4"/>
-    <GlyphID id="115" name="uni21D0_size5"/>
-    <GlyphID id="116" name="uni21D1_size2"/>
-    <GlyphID id="117" name="uni21D1_size3"/>
-    <GlyphID id="118" name="uni21D1_size4"/>
-    <GlyphID id="119" name="uni21D1_size5"/>
-    <GlyphID id="120" name="uni21D1_size6"/>
-    <GlyphID id="121" name="uni21D2_size2"/>
-    <GlyphID id="122" name="uni21D2_size3"/>
-    <GlyphID id="123" name="uni21D2_size4"/>
-    <GlyphID id="124" name="uni21D2_size5"/>
-    <GlyphID id="125" name="uni21D2_size6"/>
-    <GlyphID id="126" name="uni21D2_size7"/>
-    <GlyphID id="127" name="uni21D4_size2"/>
-    <GlyphID id="128" name="uni21D5_size2"/>
-    <GlyphID id="129" name="uni21D5_size3"/>
-    <GlyphID id="130" name="uni21E6_size2"/>
-    <GlyphID id="131" name="uni21E6_size3"/>
-    <GlyphID id="132" name="uni21E6_size4"/>
-    <GlyphID id="133" name="uni21E6_size5"/>
-    <GlyphID id="134" name="uni21E6_size6"/>
-    <GlyphID id="135" name="uni21E7_size2"/>
-    <GlyphID id="136" name="uni21E7_size3"/>
-    <GlyphID id="137" name="uni21E7_size4"/>
-    <GlyphID id="138" name="uni21E7_size5"/>
-    <GlyphID id="139" name="uni21E7_size6"/>
-    <GlyphID id="140" name="uni21E7_size7"/>
-    <GlyphID id="141" name="uni21E9_size2"/>
-  </GlyphOrder>
-
-  <head>
-    <!-- Most of this table will be recalculated by the compiler -->
-    <tableVersion value="1.0"/>
-    <fontRevision value="1.0"/>
-    <checkSumAdjustment value="0x87faf3a0"/>
-    <magicNumber value="0x5f0f3cf5"/>
-    <flags value="00000000 00001011"/>
-    <unitsPerEm value="1000"/>
-    <created value="Tue Apr 12 14:44:11 2016"/>
-    <modified value="Tue Apr 12 14:44:11 2016"/>
-    <xMin value="0"/>
-    <yMin value="0"/>
-    <xMax value="5300"/>
-    <yMax value="5500"/>
-    <macStyle value="00000000 00000000"/>
-    <lowestRecPPEM value="8"/>
-    <fontDirectionHint value="2"/>
-    <indexToLocFormat value="0"/>
-    <glyphDataFormat value="0"/>
-  </head>
-
-  <hhea>
-    <tableVersion value="1.0"/>
-    <ascent value="1000"/>
-    <descent value="0"/>
-    <lineGap value="108"/>
-    <advanceWidthMax value="1000"/>
-    <minLeftSideBearing value="0"/>
-    <minRightSideBearing value="-4300"/>
-    <xMaxExtent value="5300"/>
-    <caretSlopeRise value="1"/>
-    <caretSlopeRun value="0"/>
-    <caretOffset value="0"/>
-    <reserved0 value="0"/>
-    <reserved1 value="0"/>
-    <reserved2 value="0"/>
-    <reserved3 value="0"/>
-    <metricDataFormat value="0"/>
-    <numberOfHMetrics value="2"/>
-  </hhea>
-
-  <maxp>
-    <tableVersion value="0x5000"/>
-    <numGlyphs value="142"/>
-  </maxp>
-
-  <OS_2>
-    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
-         will be recalculated by the compiler -->
-    <version value="4"/>
-    <xAvgCharWidth value="1000"/>
-    <usWeightClass value="400"/>
-    <usWidthClass value="5"/>
-    <fsType value="00000000 00000000"/>
-    <ySubscriptXSize value="780"/>
-    <ySubscriptYSize value="840"/>
-    <ySubscriptXOffset value="0"/>
-    <ySubscriptYOffset value="168"/>
-    <ySuperscriptXSize value="780"/>
-    <ySuperscriptYSize value="840"/>
-    <ySuperscriptXOffset value="0"/>
-    <ySuperscriptYOffset value="576"/>
-    <yStrikeoutSize value="59"/>
-    <yStrikeoutPosition value="310"/>
-    <sFamilyClass value="0"/>
-    <panose>
-      <bFamilyType value="2"/>
-      <bSerifStyle value="0"/>
-      <bWeight value="5"/>
-      <bProportion value="9"/>
-      <bContrast value="0"/>
-      <bStrokeVariation value="0"/>
-      <bArmStyle value="0"/>
-      <bLetterForm value="0"/>
-      <bMidline value="0"/>
-      <bXHeight value="0"/>
-    </panose>
-    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
-    <ulUnicodeRange2 value="00000000 00000000 00000000 00100000"/>
-    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
-    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
-    <achVendID value="\x00\x00\x00\x00"/>
-    <fsSelection value="00000000 10000000"/>
-    <usFirstCharIndex value="32"/>
-    <usLastCharIndex value="9130"/>
-    <sTypoAscender value="1000"/>
-    <sTypoDescender value="0"/>
-    <sTypoLineGap value="108"/>
-    <usWinAscent value="0"/>
-    <usWinDescent value="0"/>
-    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
-    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
-    <sxHeight value="0"/>
-    <sCapHeight value="1000"/>
-    <usDefaultChar value="32"/>
-    <usBreakChar value="32"/>
-    <usMaxContext value="1"/>
-  </OS_2>
-
-  <name>
-    <namerecord nameID="0" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Copyright (c) 2016, Igalia S.L. (http://igalia.com/)
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION &amp; CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
-
-    </namerecord>
-    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Regular
-    </namerecord>
-    <namerecord nameID="3" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      FontForge 2.0 : MathTestFontFull : 12-4-2016
-    </namerecord>
-    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="5" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Version 001.000 
-    </namerecord>
-    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="14" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      http://scripts.sil.org/OFL
-    </namerecord>
-    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
-      Copyright (c) 2016, Igalia S.L. (http://igalia.com/)
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION &amp; CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
-
-    </namerecord>
-    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
-      Regular
-    </namerecord>
-    <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
-      FontForge 2.0 : MathTestFontFull : 12-4-2016
-    </namerecord>
-    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
-      Version 001.000 
-    </namerecord>
-    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
-      MathTestFontFull
-    </namerecord>
-    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
-      http://scripts.sil.org/OFL
-    </namerecord>
-  </name>
-
-  <cmap>
-    <tableVersion version="0"/>
-    <cmap_format_4 platformID="0" platEncID="3" language="0">
-      <map code="0x20" name="space"/><!-- SPACE -->
-      <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
-      <map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
-      <map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
-      <map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
-      <map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
-      <map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
-      <map code="0x47" name="G"/><!-- LATIN CAPITAL LETTER G -->
-      <map code="0x48" name="H"/><!-- LATIN CAPITAL LETTER H -->
-      <map code="0x49" name="I"/><!-- LATIN CAPITAL LETTER I -->
-      <map code="0x4a" name="J"/><!-- LATIN CAPITAL LETTER J -->
-      <map code="0x4b" name="K"/><!-- LATIN CAPITAL LETTER K -->
-      <map code="0x4c" name="L"/><!-- LATIN CAPITAL LETTER L -->
-      <map code="0x4d" name="M"/><!-- LATIN CAPITAL LETTER M -->
-      <map code="0x4e" name="N"/><!-- LATIN CAPITAL LETTER N -->
-      <map code="0x4f" name="O"/><!-- LATIN CAPITAL LETTER O -->
-      <map code="0x50" name="P"/><!-- LATIN CAPITAL LETTER P -->
-      <map code="0x51" name="Q"/><!-- LATIN CAPITAL LETTER Q -->
-      <map code="0x52" name="R"/><!-- LATIN CAPITAL LETTER R -->
-      <map code="0x53" name="S"/><!-- LATIN CAPITAL LETTER S -->
-      <map code="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
-      <map code="0x55" name="U"/><!-- LATIN CAPITAL LETTER U -->
-      <map code="0x56" name="V"/><!-- LATIN CAPITAL LETTER V -->
-      <map code="0x57" name="W"/><!-- LATIN CAPITAL LETTER W -->
-      <map code="0x58" name="X"/><!-- LATIN CAPITAL LETTER X -->
-      <map code="0x59" name="Y"/><!-- LATIN CAPITAL LETTER Y -->
-      <map code="0x5a" name="Z"/><!-- LATIN CAPITAL LETTER Z -->
-      <map code="0x5f" name="underscore"/><!-- LOW LINE -->
-      <map code="0x7b" name="braceleft"/><!-- LEFT CURLY BRACKET -->
-      <map code="0x2190" name="arrowleft"/><!-- LEFTWARDS ARROW -->
-      <map code="0x2191" name="arrowup"/><!-- UPWARDS ARROW -->
-      <map code="0x2192" name="arrowright"/><!-- RIGHTWARDS ARROW -->
-      <map code="0x2193" name="arrowdown"/><!-- DOWNWARDS ARROW -->
-      <map code="0x2194" name="arrowboth"/><!-- LEFT RIGHT ARROW -->
-      <map code="0x2195" name="arrowupdn"/><!-- UP DOWN ARROW -->
-      <map code="0x21a4" name="uni21A4"/><!-- LEFTWARDS ARROW FROM BAR -->
-      <map code="0x21a5" name="uni21A5"/><!-- UPWARDS ARROW FROM BAR -->
-      <map code="0x21a6" name="uni21A6"/><!-- RIGHTWARDS ARROW FROM BAR -->
-      <map code="0x21a7" name="uni21A7"/><!-- DOWNWARDS ARROW FROM BAR -->
-      <map code="0x21c7" name="uni21C7"/><!-- LEFTWARDS PAIRED ARROWS -->
-      <map code="0x21c8" name="uni21C8"/><!-- UPWARDS PAIRED ARROWS -->
-      <map code="0x21c9" name="uni21C9"/><!-- RIGHTWARDS PAIRED ARROWS -->
-      <map code="0x21ca" name="uni21CA"/><!-- DOWNWARDS PAIRED ARROWS -->
-      <map code="0x21d0" name="arrowdblleft"/><!-- LEFTWARDS DOUBLE ARROW -->
-      <map code="0x21d1" name="arrowdblup"/><!-- UPWARDS DOUBLE ARROW -->
-      <map code="0x21d2" name="arrowdblright"/><!-- RIGHTWARDS DOUBLE ARROW -->
-      <map code="0x21d3" name="arrowdbldown"/><!-- DOWNWARDS DOUBLE ARROW -->
-      <map code="0x21d4" name="arrowdblboth"/><!-- LEFT RIGHT DOUBLE ARROW -->
-      <map code="0x21d5" name="uni21D5"/><!-- UP DOWN DOUBLE ARROW -->
-      <map code="0x21e6" name="uni21E6"/><!-- LEFTWARDS WHITE ARROW -->
-      <map code="0x21e7" name="uni21E7"/><!-- UPWARDS WHITE ARROW -->
-      <map code="0x21e8" name="uni21E8"/><!-- RIGHTWARDS WHITE ARROW -->
-      <map code="0x21e9" name="uni21E9"/><!-- DOWNWARDS WHITE ARROW -->
-      <map code="0x23a7" name="uni23A7"/><!-- LEFT CURLY BRACKET UPPER HOOK -->
-      <map code="0x23a8" name="uni23A8"/><!-- LEFT CURLY BRACKET MIDDLE PIECE -->
-      <map code="0x23a9" name="uni23A9"/><!-- LEFT CURLY BRACKET LOWER HOOK -->
-      <map code="0x23aa" name="uni23AA"/><!-- CURLY BRACKET EXTENSION -->
-    </cmap_format_4>
-    <cmap_format_0 platformID="1" platEncID="0" language="0">
-      <map code="0x0" name="space"/>
-      <map code="0x1" name=".notdef"/>
-      <map code="0x2" name=".notdef"/>
-      <map code="0x3" name=".notdef"/>
-      <map code="0x4" name=".notdef"/>
-      <map code="0x5" name=".notdef"/>
-      <map code="0x6" name=".notdef"/>
-      <map code="0x7" name=".notdef"/>
-      <map code="0x8" name=".notdef"/>
-      <map code="0x9" name=".notdef"/>
-      <map code="0xa" name=".notdef"/>
-      <map code="0xb" name=".notdef"/>
-      <map code="0xc" name=".notdef"/>
-      <map code="0xd" name=".notdef"/>
-      <map code="0xe" name=".notdef"/>
-      <map code="0xf" name=".notdef"/>
-      <map code="0x10" name=".notdef"/>
-      <map code="0x11" name=".notdef"/>
-      <map code="0x12" name=".notdef"/>
-      <map code="0x13" name=".notdef"/>
-      <map code="0x14" name=".notdef"/>
-      <map code="0x15" name=".notdef"/>
-      <map code="0x16" name=".notdef"/>
-      <map code="0x17" name=".notdef"/>
-      <map code="0x18" name=".notdef"/>
-      <map code="0x19" name=".notdef"/>
-      <map code="0x1a" name=".notdef"/>
-      <map code="0x1b" name=".notdef"/>
-      <map code="0x1c" name=".notdef"/>
-      <map code="0x1d" name=".notdef"/>
-      <map code="0x1e" name=".notdef"/>
-      <map code="0x1f" name=".notdef"/>
-      <map code="0x20" name="space"/>
-      <map code="0x21" name=".notdef"/>
-      <map code="0x22" name=".notdef"/>
-      <map code="0x23" name=".notdef"/>
-      <map code="0x24" name=".notdef"/>
-      <map code="0x25" name=".notdef"/>
-      <map code="0x26" name=".notdef"/>
-      <map code="0x27" name=".notdef"/>
-      <map code="0x28" name=".notdef"/>
-      <map code="0x29" name=".notdef"/>
-      <map code="0x2a" name=".notdef"/>
-      <map code="0x2b" name=".notdef"/>
-      <map code="0x2c" name=".notdef"/>
-      <map code="0x2d" name=".notdef"/>
-      <map code="0x2e" name=".notdef"/>
-      <map code="0x2f" name=".notdef"/>
-      <map code="0x30" name=".notdef"/>
-      <map code="0x31" name=".notdef"/>
-      <map code="0x32" name=".notdef"/>
-      <map code="0x33" name=".notdef"/>
-      <map code="0x34" name=".notdef"/>
-      <map code="0x35" name=".notdef"/>
-      <map code="0x36" name=".notdef"/>
-      <map code="0x37" name=".notdef"/>
-      <map code="0x38" name=".notdef"/>
-      <map code="0x39" name=".notdef"/>
-      <map code="0x3a" name=".notdef"/>
-      <map code="0x3b" name=".notdef"/>
-      <map code="0x3c" name=".notdef"/>
-      <map code="0x3d" name=".notdef"/>
-      <map code="0x3e" name=".notdef"/>
-      <map code="0x3f" name=".notdef"/>
-      <map code="0x40" name=".notdef"/>
-      <map code="0x41" name="A"/>
-      <map code="0x42" name="B"/>
-      <map code="0x43" name="C"/>
-      <map code="0x44" name="D"/>
-      <map code="0x45" name="E"/>
-      <map code="0x46" name="F"/>
-      <map code="0x47" name="G"/>
-      <map code="0x48" name="H"/>
-      <map code="0x49" name="I"/>
-      <map code="0x4a" name="J"/>
-      <map code="0x4b" name="K"/>
-      <map code="0x4c" name="L"/>
-      <map code="0x4d" name="M"/>
-      <map code="0x4e" name="N"/>
-      <map code="0x4f" name="O"/>
-      <map code="0x50" name="P"/>
-      <map code="0x51" name="Q"/>
-      <map code="0x52" name="R"/>
-      <map code="0x53" name="S"/>
-      <map code="0x54" name="T"/>
-      <map code="0x55" name="U"/>
-      <map code="0x56" name="V"/>
-      <map code="0x57" name="W"/>
-      <map code="0x58" name="X"/>
-      <map code="0x59" name="Y"/>
-      <map code="0x5a" name="Z"/>
-      <map code="0x5b" name=".notdef"/>
-      <map code="0x5c" name=".notdef"/>
-      <map code="0x5d" name=".notdef"/>
-      <map code="0x5e" name=".notdef"/>
-      <map code="0x5f" name="underscore"/>
-      <map code="0x60" name=".notdef"/>
-      <map code="0x61" name=".notdef"/>
-      <map code="0x62" name=".notdef"/>
-      <map code="0x63" name=".notdef"/>
-      <map code="0x64" name=".notdef"/>
-      <map code="0x65" name=".notdef"/>
-      <map code="0x66" name=".notdef"/>
-      <map code="0x67" name=".notdef"/>
-      <map code="0x68" name=".notdef"/>
-      <map code="0x69" name=".notdef"/>
-      <map code="0x6a" name=".notdef"/>
-      <map code="0x6b" name=".notdef"/>
-      <map code="0x6c" name=".notdef"/>
-      <map code="0x6d" name=".notdef"/>
-      <map code="0x6e" name=".notdef"/>
-      <map code="0x6f" name=".notdef"/>
-      <map code="0x70" name=".notdef"/>
-      <map code="0x71" name=".notdef"/>
-      <map code="0x72" name=".notdef"/>
-      <map code="0x73" name=".notdef"/>
-      <map code="0x74" name=".notdef"/>
-      <map code="0x75" name=".notdef"/>
-      <map code="0x76" name=".notdef"/>
-      <map code="0x77" name=".notdef"/>
-      <map code="0x78" name=".notdef"/>
-      <map code="0x79" name=".notdef"/>
-      <map code="0x7a" name=".notdef"/>
-      <map code="0x7b" name="braceleft"/>
-      <map code="0x7c" name=".notdef"/>
-      <map code="0x7d" name=".notdef"/>
-      <map code="0x7e" name=".notdef"/>
-      <map code="0x7f" name=".notdef"/>
-      <map code="0x80" name=".notdef"/>
-      <map code="0x81" name=".notdef"/>
-      <map code="0x82" name=".notdef"/>
-      <map code="0x83" name=".notdef"/>
-      <map code="0x84" name=".notdef"/>
-      <map code="0x85" name=".notdef"/>
-      <map code="0x86" name=".notdef"/>
-      <map code="0x87" name=".notdef"/>
-      <map code="0x88" name=".notdef"/>
-      <map code="0x89" name=".notdef"/>
-      <map code="0x8a" name=".notdef"/>
-      <map code="0x8b" name=".notdef"/>
-      <map code="0x8c" name=".notdef"/>
-      <map code="0x8d" name=".notdef"/>
-      <map code="0x8e" name=".notdef"/>
-      <map code="0x8f" name=".notdef"/>
-      <map code="0x90" name=".notdef"/>
-      <map code="0x91" name=".notdef"/>
-      <map code="0x92" name=".notdef"/>
-      <map code="0x93" name=".notdef"/>
-      <map code="0x94" name=".notdef"/>
-      <map code="0x95" name=".notdef"/>
-      <map code="0x96" name=".notdef"/>
-      <map code="0x97" name=".notdef"/>
-      <map code="0x98" name=".notdef"/>
-      <map code="0x99" name=".notdef"/>
-      <map code="0x9a" name=".notdef"/>
-      <map code="0x9b" name=".notdef"/>
-      <map code="0x9c" name=".notdef"/>
-      <map code="0x9d" name=".notdef"/>
-      <map code="0x9e" name=".notdef"/>
-      <map code="0x9f" name=".notdef"/>
-      <map code="0xa0" name=".notdef"/>
-      <map code="0xa1" name=".notdef"/>
-      <map code="0xa2" name=".notdef"/>
-      <map code="0xa3" name=".notdef"/>
-      <map code="0xa4" name=".notdef"/>
-      <map code="0xa5" name=".notdef"/>
-      <map code="0xa6" name=".notdef"/>
-      <map code="0xa7" name=".notdef"/>
-      <map code="0xa8" name=".notdef"/>
-      <map code="0xa9" name=".notdef"/>
-      <map code="0xaa" name=".notdef"/>
-      <map code="0xab" name=".notdef"/>
-      <map code="0xac" name=".notdef"/>
-      <map code="0xad" name=".notdef"/>
-      <map code="0xae" name=".notdef"/>
-      <map code="0xaf" name=".notdef"/>
-      <map code="0xb0" name=".notdef"/>
-      <map code="0xb1" name=".notdef"/>
-      <map code="0xb2" name=".notdef"/>
-      <map code="0xb3" name=".notdef"/>
-      <map code="0xb4" name=".notdef"/>
-      <map code="0xb5" name=".notdef"/>
-      <map code="0xb6" name=".notdef"/>
-      <map code="0xb7" name=".notdef"/>
-      <map code="0xb8" name=".notdef"/>
-      <map code="0xb9" name=".notdef"/>
-      <map code="0xba" name=".notdef"/>
-      <map code="0xbb" name=".notdef"/>
-      <map code="0xbc" name=".notdef"/>
-      <map code="0xbd" name=".notdef"/>
-      <map code="0xbe" name=".notdef"/>
-      <map code="0xbf" name=".notdef"/>
-      <map code="0xc0" name=".notdef"/>
-      <map code="0xc1" name=".notdef"/>
-      <map code="0xc2" name=".notdef"/>
-      <map code="0xc3" name=".notdef"/>
-      <map code="0xc4" name=".notdef"/>
-      <map code="0xc5" name=".notdef"/>
-      <map code="0xc6" name=".notdef"/>
-      <map code="0xc7" name=".notdef"/>
-      <map code="0xc8" name=".notdef"/>
-      <map code="0xc9" name=".notdef"/>
-      <map code="0xca" name=".notdef"/>
-      <map code="0xcb" name=".notdef"/>
-      <map code="0xcc" name=".notdef"/>
-      <map code="0xcd" name=".notdef"/>
-      <map code="0xce" name=".notdef"/>
-      <map code="0xcf" name=".notdef"/>
-      <map code="0xd0" name=".notdef"/>
-      <map code="0xd1" name=".notdef"/>
-      <map code="0xd2" name=".notdef"/>
-      <map code="0xd3" name=".notdef"/>
-      <map code="0xd4" name=".notdef"/>
-      <map code="0xd5" name=".notdef"/>
-      <map code="0xd6" name=".notdef"/>
-      <map code="0xd7" name=".notdef"/>
-      <map code="0xd8" name=".notdef"/>
-      <map code="0xd9" name=".notdef"/>
-      <map code="0xda" name=".notdef"/>
-      <map code="0xdb" name=".notdef"/>
-      <map code="0xdc" name=".notdef"/>
-      <map code="0xdd" name=".notdef"/>
-      <map code="0xde" name=".notdef"/>
-      <map code="0xdf" name=".notdef"/>
-      <map code="0xe0" name=".notdef"/>
-      <map code="0xe1" name=".notdef"/>
-      <map code="0xe2" name=".notdef"/>
-      <map code="0xe3" name=".notdef"/>
-      <map code="0xe4" name=".notdef"/>
-      <map code="0xe5" name=".notdef"/>
-      <map code="0xe6" name=".notdef"/>
-      <map code="0xe7" name=".notdef"/>
-      <map code="0xe8" name=".notdef"/>
-      <map code="0xe9" name=".notdef"/>
-      <map code="0xea" name=".notdef"/>
-      <map code="0xeb" name=".notdef"/>
-      <map code="0xec" name=".notdef"/>
-      <map code="0xed" name=".notdef"/>
-      <map code="0xee" name=".notdef"/>
-      <map code="0xef" name=".notdef"/>
-      <map code="0xf0" name=".notdef"/>
-      <map code="0xf1" name=".notdef"/>
-      <map code="0xf2" name=".notdef"/>
-      <map code="0xf3" name=".notdef"/>
-      <map code="0xf4" name=".notdef"/>
-      <map code="0xf5" name=".notdef"/>
-      <map code="0xf6" name=".notdef"/>
-      <map code="0xf7" name=".notdef"/>
-      <map code="0xf8" name=".notdef"/>
-      <map code="0xf9" name=".notdef"/>
-      <map code="0xfa" name=".notdef"/>
-      <map code="0xfb" name=".notdef"/>
-      <map code="0xfc" name=".notdef"/>
-      <map code="0xfd" name=".notdef"/>
-      <map code="0xfe" name=".notdef"/>
-      <map code="0xff" name=".notdef"/>
-    </cmap_format_0>
-    <cmap_format_4 platformID="3" platEncID="1" language="0">
-      <map code="0x20" name="space"/><!-- SPACE -->
-      <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
-      <map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
-      <map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
-      <map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
-      <map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
-      <map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
-      <map code="0x47" name="G"/><!-- LATIN CAPITAL LETTER G -->
-      <map code="0x48" name="H"/><!-- LATIN CAPITAL LETTER H -->
-      <map code="0x49" name="I"/><!-- LATIN CAPITAL LETTER I -->
-      <map code="0x4a" name="J"/><!-- LATIN CAPITAL LETTER J -->
-      <map code="0x4b" name="K"/><!-- LATIN CAPITAL LETTER K -->
-      <map code="0x4c" name="L"/><!-- LATIN CAPITAL LETTER L -->
-      <map code="0x4d" name="M"/><!-- LATIN CAPITAL LETTER M -->
-      <map code="0x4e" name="N"/><!-- LATIN CAPITAL LETTER N -->
-      <map code="0x4f" name="O"/><!-- LATIN CAPITAL LETTER O -->
-      <map code="0x50" name="P"/><!-- LATIN CAPITAL LETTER P -->
-      <map code="0x51" name="Q"/><!-- LATIN CAPITAL LETTER Q -->
-      <map code="0x52" name="R"/><!-- LATIN CAPITAL LETTER R -->
-      <map code="0x53" name="S"/><!-- LATIN CAPITAL LETTER S -->
-      <map code="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
-      <map code="0x55" name="U"/><!-- LATIN CAPITAL LETTER U -->
-      <map code="0x56" name="V"/><!-- LATIN CAPITAL LETTER V -->
-      <map code="0x57" name="W"/><!-- LATIN CAPITAL LETTER W -->
-      <map code="0x58" name="X"/><!-- LATIN CAPITAL LETTER X -->
-      <map code="0x59" name="Y"/><!-- LATIN CAPITAL LETTER Y -->
-      <map code="0x5a" name="Z"/><!-- LATIN CAPITAL LETTER Z -->
-      <map code="0x5f" name="underscore"/><!-- LOW LINE -->
-      <map code="0x7b" name="braceleft"/><!-- LEFT CURLY BRACKET -->
-      <map code="0x2190" name="arrowleft"/><!-- LEFTWARDS ARROW -->
-      <map code="0x2191" name="arrowup"/><!-- UPWARDS ARROW -->
-      <map code="0x2192" name="arrowright"/><!-- RIGHTWARDS ARROW -->
-      <map code="0x2193" name="arrowdown"/><!-- DOWNWARDS ARROW -->
-      <map code="0x2194" name="arrowboth"/><!-- LEFT RIGHT ARROW -->
-      <map code="0x2195" name="arrowupdn"/><!-- UP DOWN ARROW -->
-      <map code="0x21a4" name="uni21A4"/><!-- LEFTWARDS ARROW FROM BAR -->
-      <map code="0x21a5" name="uni21A5"/><!-- UPWARDS ARROW FROM BAR -->
-      <map code="0x21a6" name="uni21A6"/><!-- RIGHTWARDS ARROW FROM BAR -->
-      <map code="0x21a7" name="uni21A7"/><!-- DOWNWARDS ARROW FROM BAR -->
-      <map code="0x21c7" name="uni21C7"/><!-- LEFTWARDS PAIRED ARROWS -->
-      <map code="0x21c8" name="uni21C8"/><!-- UPWARDS PAIRED ARROWS -->
-      <map code="0x21c9" name="uni21C9"/><!-- RIGHTWARDS PAIRED ARROWS -->
-      <map code="0x21ca" name="uni21CA"/><!-- DOWNWARDS PAIRED ARROWS -->
-      <map code="0x21d0" name="arrowdblleft"/><!-- LEFTWARDS DOUBLE ARROW -->
-      <map code="0x21d1" name="arrowdblup"/><!-- UPWARDS DOUBLE ARROW -->
-      <map code="0x21d2" name="arrowdblright"/><!-- RIGHTWARDS DOUBLE ARROW -->
-      <map code="0x21d3" name="arrowdbldown"/><!-- DOWNWARDS DOUBLE ARROW -->
-      <map code="0x21d4" name="arrowdblboth"/><!-- LEFT RIGHT DOUBLE ARROW -->
-      <map code="0x21d5" name="uni21D5"/><!-- UP DOWN DOUBLE ARROW -->
-      <map code="0x21e6" name="uni21E6"/><!-- LEFTWARDS WHITE ARROW -->
-      <map code="0x21e7" name="uni21E7"/><!-- UPWARDS WHITE ARROW -->
-      <map code="0x21e8" name="uni21E8"/><!-- RIGHTWARDS WHITE ARROW -->
-      <map code="0x21e9" name="uni21E9"/><!-- DOWNWARDS WHITE ARROW -->
-      <map code="0x23a7" name="uni23A7"/><!-- LEFT CURLY BRACKET UPPER HOOK -->
-      <map code="0x23a8" name="uni23A8"/><!-- LEFT CURLY BRACKET MIDDLE PIECE -->
-      <map code="0x23a9" name="uni23A9"/><!-- LEFT CURLY BRACKET LOWER HOOK -->
-      <map code="0x23aa" name="uni23AA"/><!-- CURLY BRACKET EXTENSION -->
-    </cmap_format_4>
-  </cmap>
-
-  <post>
-    <formatType value="3.0"/>
-    <italicAngle value="0.0"/>
-    <underlinePosition value="-125"/>
-    <underlineThickness value="50"/>
-    <isFixedPitch value="1"/>
-    <minMemType42 value="0"/>
-    <maxMemType42 value="0"/>
-    <minMemType1 value="0"/>
-    <maxMemType1 value="0"/>
-  </post>
-
-  <CFF>
-    <CFFFont name="MathTestFontFull">
-      <version value="001.000"/>
-      <Notice value="Copyright (c) 2016 Igalia S.L."/>
-      <FullName value="MathTestFontFull"/>
-      <FamilyName value="MathTestFontFull"/>
-      <Weight value="Regular"/>
-      <isFixedPitch value="1"/>
-      <ItalicAngle value="0"/>
-      <UnderlineThickness value="50"/>
-      <PaintType value="0"/>
-      <CharstringType value="2"/>
-      <FontMatrix value="0.001 0 0 0.001 0 0"/>
-      <FontBBox value="0 0 5300 5500"/>
-      <StrokeWidth value="0"/>
-      <!-- charset is dumped separately as the 'GlyphOrder' element -->
-      <Encoding name="StandardEncoding"/>
-      <Private>
-        <BlueValues value="-20 0 1000 1000"/>
-        <BlueScale value="0.039625"/>
-        <BlueShift value="0"/>
-        <BlueFuzz value="1"/>
-        <StdHW value="250"/>
-        <StdVW value="1000"/>
-        <StemSnapH value="166 200 250 333 500"/>
-        <StemSnapV value="166 200 250 333 500 1000"/>
-        <ForceBold value="0"/>
-        <LanguageGroup value="0"/>
-        <ExpansionFactor value="0.06"/>
-        <initialRandomSeed value="0"/>
-        <defaultWidthX value="1000"/>
-        <nominalWidthX value="0"/>
-        <Subrs>
-          <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
-          <CharString index="0">
-            1000 1000 -1000 hlineto
-            return
-          </CharString>
-        </Subrs>
-      </Private>
-      <CharStrings>
-        <CharString name=".notdef">
-          0 50 566 50 hstem
-          50 50 800 50 vstem
-          50 hmoveto
-          900 666 -900 hlineto
-          50 -616 rmoveto
-          566 800 -566 vlineto
-          endchar
-        </CharString>
-        <CharString name="A">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="B">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="C">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="D">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="E">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="F">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="G">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="H">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="I">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="J">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="K">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="L">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="M">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="N">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="O">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="P">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="Q">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="R">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="S">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="T">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="U">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="V">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="W">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="X">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="Y">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="Z">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowboth">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdblboth">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdbldown">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdblleft">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdblright">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdblup">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowdown">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowleft">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowright">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowup">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="arrowupdn">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="bottom">
-          0 200 800 -20 hstem
-          400 200 vstem
-          0 vmoveto
-          1000 200 -400 800 -200 -800 -400 hlineto
-          endchar
-        </CharString>
-        <CharString name="braceleft">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="center">
-          21 -21 400 200 400 -20 hstem
-          400 200 vstem
-          400 hmoveto
-          200 400 400 200 -400 400 -200 -400 -400 -200 400 hlineto
-          endchar
-        </CharString>
-        <CharString name="horizontal">
-          400 200 hstem
-          400 vmoveto
-          1000 200 -1000 hlineto
-          endchar
-        </CharString>
-        <CharString name="left">
-          21 -21 400 200 400 -20 hstem
-          0 200 vstem
-          0 vmoveto
-          200 400 800 200 -800 400 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="right">
-          21 -21 400 200 400 -20 hstem
-          800 200 vstem
-          800 hmoveto
-          200 1000 -200 -400 -800 -200 800 hlineto
-          endchar
-        </CharString>
-        <CharString name="space">
-          endchar
-        </CharString>
-        <CharString name="top">
-          21 -21 800 200 hstem
-          400 200 vstem
-          400 hmoveto
-          200 800 400 200 -1000 -200 400 hlineto
-          endchar
-        </CharString>
-        <CharString name="underscore">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni2190_size2">
-          0 250 hstem
-          0 vmoveto
-          2150 250 -2150 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2190_size3">
-          0 200 hstem
-          0 vmoveto
-          2400 200 -2400 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2190_size4">
-          0 166 hstem
-          0 vmoveto
-          2900 166 -2900 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2191_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2250 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2191_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2500 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2191_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3000 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2191_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 3750 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2192_size2">
-          0 250 hstem
-          0 vmoveto
-          2350 250 -2350 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2192_size3">
-          0 200 hstem
-          0 vmoveto
-          2600 200 -2600 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2192_size4">
-          0 166 hstem
-          0 vmoveto
-          3100 166 -3100 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2192_size5">
-          0 500 hstem
-          0 vmoveto
-          3850 500 -3850 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2192_size6">
-          0 333 hstem
-          0 vmoveto
-          4100 333 -4100 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2450 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2700 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3200 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 3950 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size6">
-          21 -21 hstem
-          0 333 vstem
-          0 vmoveto
-          333 4200 -333 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2193_size7">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 4700 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni2195_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2650 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A4">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21A4_size2">
-          0 250 hstem
-          0 vmoveto
-          2250 250 -2250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A4_size3">
-          0 200 hstem
-          0 vmoveto
-          2500 200 -2500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A5">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21A5_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2350 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A5_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2600 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A5_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3100 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A6">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21A6_size2">
-          0 250 hstem
-          0 vmoveto
-          2450 250 -2450 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A6_size3">
-          0 200 hstem
-          0 vmoveto
-          2700 200 -2700 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A6_size4">
-          0 166 hstem
-          0 vmoveto
-          3200 166 -3200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A6_size5">
-          0 500 hstem
-          0 vmoveto
-          3950 500 -3950 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A7">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21A7_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2550 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A7_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2800 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A7_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3300 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A7_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 4050 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21A7_size6">
-          21 -21 hstem
-          0 333 vstem
-          0 vmoveto
-          333 4300 -333 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C7">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21C7_size2">
-          0 250 hstem
-          0 vmoveto
-          1950 250 -1950 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C7_size3">
-          0 200 hstem
-          0 vmoveto
-          2200 200 -2200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C8">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21C8_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2050 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C8_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2300 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C8_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 2800 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C9">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21C9_size2">
-          0 250 hstem
-          0 vmoveto
-          2150 250 -2150 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C9_size3">
-          0 200 hstem
-          0 vmoveto
-          2400 200 -2400 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C9_size4">
-          0 166 hstem
-          0 vmoveto
-          2900 166 -2900 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21C9_size5">
-          0 500 hstem
-          0 vmoveto
-          3650 500 -3650 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21CA">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21CA_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2250 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21CA_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 2500 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21CA_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3000 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21CA_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 3750 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21CA_size6">
-          21 -21 hstem
-          0 333 vstem
-          0 vmoveto
-          333 4000 -333 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D0_size2">
-          0 250 hstem
-          0 vmoveto
-          2850 250 -2850 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D0_size3">
-          0 200 hstem
-          0 vmoveto
-          3100 200 -3100 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D0_size4">
-          0 166 hstem
-          0 vmoveto
-          3600 166 -3600 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D0_size5">
-          0 500 hstem
-          0 vmoveto
-          4350 500 -4350 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D1_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 2950 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D1_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 3200 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D1_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 3700 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D1_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 4450 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D1_size6">
-          21 -21 hstem
-          0 333 vstem
-          0 vmoveto
-          333 4700 -333 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size2">
-          0 250 hstem
-          0 vmoveto
-          3050 250 -3050 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size3">
-          0 200 hstem
-          0 vmoveto
-          3300 200 -3300 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size4">
-          0 166 hstem
-          0 vmoveto
-          3800 166 -3800 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size5">
-          0 500 hstem
-          0 vmoveto
-          4550 500 -4550 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size6">
-          0 333 hstem
-          0 vmoveto
-          4800 333 -4800 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D2_size7">
-          0 250 hstem
-          0 vmoveto
-          5300 250 -5300 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D4_size2">
-          0 250 hstem
-          0 vmoveto
-          3250 250 -3250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D5">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21D5_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 3350 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21D5_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 3600 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E6">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21E6_size2">
-          0 250 hstem
-          0 vmoveto
-          3150 250 -3150 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E6_size3">
-          0 200 hstem
-          0 vmoveto
-          3400 200 -3400 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E6_size4">
-          0 166 hstem
-          0 vmoveto
-          3900 166 -3900 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E6_size5">
-          0 500 hstem
-          0 vmoveto
-          4650 500 -4650 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E6_size6">
-          0 333 hstem
-          0 vmoveto
-          4900 333 -4900 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 3250 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size3">
-          21 -21 hstem
-          0 200 vstem
-          0 vmoveto
-          200 3500 -200 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size4">
-          21 -21 hstem
-          0 166 vstem
-          0 vmoveto
-          166 4000 -166 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size5">
-          21 -21 hstem
-          0 500 vstem
-          0 vmoveto
-          500 4750 -500 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size6">
-          21 -21 hstem
-          0 333 vstem
-          0 vmoveto
-          333 5000 -333 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E7_size7">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 5500 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni21E8">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21E9">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni21E9_size2">
-          21 -21 hstem
-          0 250 vstem
-          0 vmoveto
-          250 3450 -250 hlineto
-          endchar
-        </CharString>
-        <CharString name="uni23A7">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni23A8">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni23A9">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="uni23AA">
-          21 -21 1000 -20 hstem
-          0 1000 vstem
-          0 vmoveto
-          -107 callsubr
-          endchar
-        </CharString>
-        <CharString name="vertical">
-          21 -21 1000 -20 hstem
-          400 200 vstem
-          400 hmoveto
-          200 1000 -200 hlineto
-          endchar
-        </CharString>
-      </CharStrings>
-    </CFFFont>
-
-    <GlobalSubrs>
-      <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
-    </GlobalSubrs>
-  </CFF>
-
-  <FFTM>
-    <!-- FontForge's timestamp, font source creation and modification dates -->
-    <version value="1"/>
-    <FFTimeStamp value="Sun Mar 20 10:09:51 2016"/>
-    <sourceCreated value="Tue Apr 12 14:44:11 2016"/>
-    <sourceModified value="Tue Apr 12 14:44:11 2016"/>
-  </FFTM>
-
-  <MATH>
-    <Version value="1.0"/>
-    <MathConstants>
-      <ScriptPercentScaleDown value="87"/>
-      <ScriptScriptPercentScaleDown value="76"/>
-      <DelimitedSubFormulaMinHeight value="100"/>
-      <DisplayOperatorMinHeight value="200"/>
-      <MathLeading>
-        <Value value="300"/>
-      </MathLeading>
-      <AxisHeight>
-        <Value value="400"/>
-      </AxisHeight>
-      <AccentBaseHeight>
-        <Value value="500"/>
-      </AccentBaseHeight>
-      <FlattenedAccentBaseHeight>
-        <Value value="600"/>
-      </FlattenedAccentBaseHeight>
-      <SubscriptShiftDown>
-        <Value value="700"/>
-      </SubscriptShiftDown>
-      <SubscriptTopMax>
-        <Value value="800"/>
-      </SubscriptTopMax>
-      <SubscriptBaselineDropMin>
-        <Value value="900"/>
-      </SubscriptBaselineDropMin>
-      <SuperscriptShiftUp>
-        <Value value="1100"/>
-      </SuperscriptShiftUp>
-      <SuperscriptShiftUpCramped>
-        <Value value="1200"/>
-      </SuperscriptShiftUpCramped>
-      <SuperscriptBottomMin>
-        <Value value="1300"/>
-      </SuperscriptBottomMin>
-      <SuperscriptBaselineDropMax>
-        <Value value="1400"/>
-      </SuperscriptBaselineDropMax>
-      <SubSuperscriptGapMin>
-        <Value value="1500"/>
-      </SubSuperscriptGapMin>
-      <SuperscriptBottomMaxWithSubscript>
-        <Value value="1600"/>
-      </SuperscriptBottomMaxWithSubscript>
-      <SpaceAfterScript>
-        <Value value="1700"/>
-      </SpaceAfterScript>
-      <UpperLimitGapMin>
-        <Value value="1800"/>
-      </UpperLimitGapMin>
-      <UpperLimitBaselineRiseMin>
-        <Value value="1900"/>
-      </UpperLimitBaselineRiseMin>
-      <LowerLimitGapMin>
-        <Value value="2200"/>
-      </LowerLimitGapMin>
-      <LowerLimitBaselineDropMin>
-        <Value value="2300"/>
-      </LowerLimitBaselineDropMin>
-      <StackTopShiftUp>
-        <Value value="2400"/>
-      </StackTopShiftUp>
-      <StackTopDisplayStyleShiftUp>
-        <Value value="2500"/>
-      </StackTopDisplayStyleShiftUp>
-      <StackBottomShiftDown>
-        <Value value="2600"/>
-      </StackBottomShiftDown>
-      <StackBottomDisplayStyleShiftDown>
-        <Value value="2700"/>
-      </StackBottomDisplayStyleShiftDown>
-      <StackGapMin>
-        <Value value="2800"/>
-      </StackGapMin>
-      <StackDisplayStyleGapMin>
-        <Value value="2900"/>
-      </StackDisplayStyleGapMin>
-      <StretchStackTopShiftUp>
-        <Value value="3000"/>
-      </StretchStackTopShiftUp>
-      <StretchStackBottomShiftDown>
-        <Value value="3100"/>
-      </StretchStackBottomShiftDown>
-      <StretchStackGapAboveMin>
-        <Value value="3200"/>
-      </StretchStackGapAboveMin>
-      <StretchStackGapBelowMin>
-        <Value value="3300"/>
-      </StretchStackGapBelowMin>
-      <FractionNumeratorShiftUp>
-        <Value value="3400"/>
-      </FractionNumeratorShiftUp>
-      <FractionNumeratorDisplayStyleShiftUp>
-        <Value value="3500"/>
-      </FractionNumeratorDisplayStyleShiftUp>
-      <FractionDenominatorShiftDown>
-        <Value value="3600"/>
-      </FractionDenominatorShiftDown>
-      <FractionDenominatorDisplayStyleShiftDown>
-        <Value value="3700"/>
-      </FractionDenominatorDisplayStyleShiftDown>
-      <FractionNumeratorGapMin>
-        <Value value="3800"/>
-      </FractionNumeratorGapMin>
-      <FractionNumDisplayStyleGapMin>
-        <Value value="3900"/>
-      </FractionNumDisplayStyleGapMin>
-      <FractionRuleThickness>
-        <Value value="4000"/>
-      </FractionRuleThickness>
-      <FractionDenominatorGapMin>
-        <Value value="4100"/>
-      </FractionDenominatorGapMin>
-      <FractionDenomDisplayStyleGapMin>
-        <Value value="4200"/>
-      </FractionDenomDisplayStyleGapMin>
-      <SkewedFractionHorizontalGap>
-        <Value value="4300"/>
-      </SkewedFractionHorizontalGap>
-      <SkewedFractionVerticalGap>
-        <Value value="4400"/>
-      </SkewedFractionVerticalGap>
-      <OverbarVerticalGap>
-        <Value value="4500"/>
-      </OverbarVerticalGap>
-      <OverbarRuleThickness>
-        <Value value="4600"/>
-      </OverbarRuleThickness>
-      <OverbarExtraAscender>
-        <Value value="4700"/>
-      </OverbarExtraAscender>
-      <UnderbarVerticalGap>
-        <Value value="4800"/>
-      </UnderbarVerticalGap>
-      <UnderbarRuleThickness>
-        <Value value="4900"/>
-      </UnderbarRuleThickness>
-      <UnderbarExtraDescender>
-        <Value value="5000"/>
-      </UnderbarExtraDescender>
-      <RadicalVerticalGap>
-        <Value value="5100"/>
-      </RadicalVerticalGap>
-      <RadicalDisplayStyleVerticalGap>
-        <Value value="5200"/>
-      </RadicalDisplayStyleVerticalGap>
-      <RadicalRuleThickness>
-        <Value value="5300"/>
-      </RadicalRuleThickness>
-      <RadicalExtraAscender>
-        <Value value="5400"/>
-      </RadicalExtraAscender>
-      <RadicalKernBeforeDegree>
-        <Value value="5500"/>
-      </RadicalKernBeforeDegree>
-      <RadicalKernAfterDegree>
-        <Value value="5600"/>
-      </RadicalKernAfterDegree>
-      <RadicalDegreeBottomRaisePercent value="65"/>
-    </MathConstants>
-    <MathGlyphInfo>
-      <MathItalicsCorrectionInfo>
-        <Coverage Format="2">
-          <Glyph value="A"/>
-          <Glyph value="B"/>
-          <Glyph value="C"/>
-          <Glyph value="D"/>
-          <Glyph value="E"/>
-          <Glyph value="F"/>
-          <Glyph value="G"/>
-          <Glyph value="H"/>
-          <Glyph value="I"/>
-          <Glyph value="J"/>
-          <Glyph value="K"/>
-          <Glyph value="L"/>
-          <Glyph value="M"/>
-          <Glyph value="N"/>
-          <Glyph value="O"/>
-          <Glyph value="P"/>
-          <Glyph value="Q"/>
-          <Glyph value="R"/>
-          <Glyph value="S"/>
-          <Glyph value="T"/>
-          <Glyph value="U"/>
-          <Glyph value="V"/>
-          <Glyph value="W"/>
-          <Glyph value="X"/>
-          <Glyph value="Y"/>
-          <Glyph value="Z"/>
-          <Glyph value="arrowleft"/>
-          <Glyph value="arrowup"/>
-          <Glyph value="arrowright"/>
-          <Glyph value="arrowdown"/>
-          <Glyph value="arrowboth"/>
-          <Glyph value="arrowupdn"/>
-          <Glyph value="uni21A4"/>
-          <Glyph value="uni21A5"/>
-          <Glyph value="uni21A6"/>
-          <Glyph value="uni21A7"/>
-          <Glyph value="uni21C7"/>
-          <Glyph value="uni21C8"/>
-          <Glyph value="uni21C9"/>
-          <Glyph value="uni21CA"/>
-          <Glyph value="arrowdblleft"/>
-          <Glyph value="arrowdblup"/>
-          <Glyph value="arrowdblright"/>
-          <Glyph value="arrowdbldown"/>
-          <Glyph value="arrowdblboth"/>
-          <Glyph value="uni21D5"/>
-          <Glyph value="uni21E6"/>
-          <Glyph value="uni21E7"/>
-          <Glyph value="uni21E8"/>
-          <Glyph value="uni21E9"/>
-          <Glyph value="uni2190_size2"/>
-          <Glyph value="uni2190_size3"/>
-          <Glyph value="uni2190_size4"/>
-          <Glyph value="uni2191_size2"/>
-          <Glyph value="uni2191_size3"/>
-          <Glyph value="uni2191_size4"/>
-          <Glyph value="uni2191_size5"/>
-          <Glyph value="uni2192_size2"/>
-          <Glyph value="uni2192_size3"/>
-          <Glyph value="uni2192_size4"/>
-          <Glyph value="uni2192_size5"/>
-          <Glyph value="uni2192_size6"/>
-          <Glyph value="uni2193_size2"/>
-          <Glyph value="uni2193_size3"/>
-          <Glyph value="uni2193_size4"/>
-          <Glyph value="uni2193_size5"/>
-          <Glyph value="uni2193_size6"/>
-          <Glyph value="uni2193_size7"/>
-          <Glyph value="uni2195_size2"/>
-          <Glyph value="uni21A4_size2"/>
-          <Glyph value="uni21A4_size3"/>
-          <Glyph value="uni21A5_size2"/>
-          <Glyph value="uni21A5_size3"/>
-          <Glyph value="uni21A5_size4"/>
-          <Glyph value="uni21A6_size2"/>
-          <Glyph value="uni21A6_size3"/>
-          <Glyph value="uni21A6_size4"/>
-          <Glyph value="uni21A6_size5"/>
-          <Glyph value="uni21A7_size2"/>
-          <Glyph value="uni21A7_size3"/>
-          <Glyph value="uni21A7_size4"/>
-          <Glyph value="uni21A7_size5"/>
-          <Glyph value="uni21A7_size6"/>
-          <Glyph value="uni21C7_size2"/>
-          <Glyph value="uni21C7_size3"/>
-          <Glyph value="uni21C8_size2"/>
-          <Glyph value="uni21C8_size3"/>
-          <Glyph value="uni21C8_size4"/>
-          <Glyph value="uni21C9_size2"/>
-          <Glyph value="uni21C9_size3"/>
-          <Glyph value="uni21C9_size4"/>
-          <Glyph value="uni21C9_size5"/>
-          <Glyph value="uni21CA_size2"/>
-          <Glyph value="uni21CA_size3"/>
-          <Glyph value="uni21CA_size4"/>
-          <Glyph value="uni21CA_size5"/>
-          <Glyph value="uni21CA_size6"/>
-          <Glyph value="uni21D0_size2"/>
-          <Glyph value="uni21D0_size3"/>
-          <Glyph value="uni21D0_size4"/>
-          <Glyph value="uni21D0_size5"/>
-          <Glyph value="uni21D1_size2"/>
-          <Glyph value="uni21D1_size3"/>
-          <Glyph value="uni21D1_size4"/>
-          <Glyph value="uni21D1_size5"/>
-          <Glyph value="uni21D1_size6"/>
-          <Glyph value="uni21D2_size2"/>
-          <Glyph value="uni21D2_size3"/>
-          <Glyph value="uni21D2_size4"/>
-          <Glyph value="uni21D2_size5"/>
-          <Glyph value="uni21D2_size6"/>
-          <Glyph value="uni21D2_size7"/>
-          <Glyph value="uni21D4_size2"/>
-          <Glyph value="uni21D5_size2"/>
-          <Glyph value="uni21D5_size3"/>
-          <Glyph value="uni21E6_size2"/>
-          <Glyph value="uni21E6_size3"/>
-          <Glyph value="uni21E6_size4"/>
-          <Glyph value="uni21E6_size5"/>
-          <Glyph value="uni21E6_size6"/>
-          <Glyph value="uni21E7_size2"/>
-          <Glyph value="uni21E7_size3"/>
-          <Glyph value="uni21E7_size4"/>
-          <Glyph value="uni21E7_size5"/>
-          <Glyph value="uni21E7_size6"/>
-          <Glyph value="uni21E7_size7"/>
-          <Glyph value="uni21E9_size2"/>
-        </Coverage>
-        <!-- ItalicsCorrectionCount=127 -->
-        <ItalicsCorrection index="0">
-          <Value value="197"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="1">
-          <Value value="150"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="2">
-          <Value value="452"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="3">
-          <Value value="405"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="4">
-          <Value value="358"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="5">
-          <Value value="311"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="6">
-          <Value value="264"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="7">
-          <Value value="217"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="8">
-          <Value value="170"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="9">
-          <Value value="123"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="10">
-          <Value value="425"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="11">
-          <Value value="378"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="12">
-          <Value value="331"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="13">
-          <Value value="284"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="14">
-          <Value value="237"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="15">
-          <Value value="190"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="16">
-          <Value value="143"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="17">
-          <Value value="445"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="18">
-          <Value value="398"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="19">
-          <Value value="351"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="20">
-          <Value value="304"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="21">
-          <Value value="257"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="22">
-          <Value value="210"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="23">
-          <Value value="163"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="24">
-          <Value value="116"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="25">
-          <Value value="418"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="26">
-          <Value value="429"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="27">
-          <Value value="382"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="28">
-          <Value value="335"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="29">
-          <Value value="288"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="30">
-          <Value value="241"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="31">
-          <Value value="194"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="32">
-          <Value value="187"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="33">
-          <Value value="140"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="34">
-          <Value value="442"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="35">
-          <Value value="395"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="36">
-          <Value value="287"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="37">
-          <Value value="240"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="38">
-          <Value value="193"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="39">
-          <Value value="146"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="40">
-          <Value value="213"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="41">
-          <Value value="166"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="42">
-          <Value value="119"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="43">
-          <Value value="421"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="44">
-          <Value value="374"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="45">
-          <Value value="327"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="46">
-          <Value value="226"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="47">
-          <Value value="179"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="48">
-          <Value value="132"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="49">
-          <Value value="434"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="50">
-          <Value value="335"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="51">
-          <Value value="288"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="52">
-          <Value value="241"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="53">
-          <Value value="288"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="54">
-          <Value value="241"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="55">
-          <Value value="194"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="56">
-          <Value value="147"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="57">
-          <Value value="241"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="58">
-          <Value value="194"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="59">
-          <Value value="147"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="60">
-          <Value value="449"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="61">
-          <Value value="402"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="62">
-          <Value value="194"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="63">
-          <Value value="147"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="64">
-          <Value value="449"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="65">
-          <Value value="402"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="66">
-          <Value value="355"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="67">
-          <Value value="308"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="68">
-          <Value value="449"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="69">
-          <Value value="442"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="70">
-          <Value value="395"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="71">
-          <Value value="395"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="72">
-          <Value value="348"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="73">
-          <Value value="301"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="74">
-          <Value value="348"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="75">
-          <Value value="301"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="76">
-          <Value value="254"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="77">
-          <Value value="207"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="78">
-          <Value value="301"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="79">
-          <Value value="254"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="80">
-          <Value value="207"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="81">
-          <Value value="160"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="82">
-          <Value value="113"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="83">
-          <Value value="193"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="84">
-          <Value value="146"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="85">
-          <Value value="146"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="86">
-          <Value value="448"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="87">
-          <Value value="401"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="88">
-          <Value value="448"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="89">
-          <Value value="401"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="90">
-          <Value value="354"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="91">
-          <Value value="307"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="92">
-          <Value value="401"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="93">
-          <Value value="354"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="94">
-          <Value value="307"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="95">
-          <Value value="260"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="96">
-          <Value value="213"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="97">
-          <Value value="119"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="98">
-          <Value value="421"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="99">
-          <Value value="374"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="100">
-          <Value value="327"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="101">
-          <Value value="421"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="102">
-          <Value value="374"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="103">
-          <Value value="327"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="104">
-          <Value value="280"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="105">
-          <Value value="233"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="106">
-          <Value value="374"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="107">
-          <Value value="327"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="108">
-          <Value value="280"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="109">
-          <Value value="233"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="110">
-          <Value value="186"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="111">
-          <Value value="139"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="112">
-          <Value value="280"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="113">
-          <Value value="233"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="114">
-          <Value value="186"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="115">
-          <Value value="132"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="116">
-          <Value value="434"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="117">
-          <Value value="387"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="118">
-          <Value value="340"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="119">
-          <Value value="293"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="120">
-          <Value value="434"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="121">
-          <Value value="387"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="122">
-          <Value value="340"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="123">
-          <Value value="293"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="124">
-          <Value value="246"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="125">
-          <Value value="199"/>
-        </ItalicsCorrection>
-        <ItalicsCorrection index="126">
-          <Value value="340"/>
-        </ItalicsCorrection>
-      </MathItalicsCorrectionInfo>
-      <MathTopAccentAttachment>
-        <TopAccentCoverage Format="2">
-          <Glyph value="A"/>
-          <Glyph value="B"/>
-          <Glyph value="C"/>
-          <Glyph value="D"/>
-          <Glyph value="E"/>
-          <Glyph value="F"/>
-          <Glyph value="G"/>
-          <Glyph value="H"/>
-          <Glyph value="I"/>
-          <Glyph value="J"/>
-          <Glyph value="K"/>
-          <Glyph value="L"/>
-          <Glyph value="M"/>
-          <Glyph value="N"/>
-          <Glyph value="O"/>
-          <Glyph value="P"/>
-          <Glyph value="Q"/>
-          <Glyph value="R"/>
-          <Glyph value="S"/>
-          <Glyph value="T"/>
-          <Glyph value="U"/>
-          <Glyph value="V"/>
-          <Glyph value="W"/>
-          <Glyph value="X"/>
-          <Glyph value="Y"/>
-          <Glyph value="Z"/>
-        </TopAccentCoverage>
-        <!-- TopAccentAttachmentCount=26 -->
-        <TopAccentAttachment index="0">
-          <Value value="458"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="1">
-          <Value value="430"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="2">
-          <Value value="402"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="3">
-          <Value value="374"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="4">
-          <Value value="346"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="5">
-          <Value value="318"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="6">
-          <Value value="290"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="7">
-          <Value value="262"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="8">
-          <Value value="234"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="9">
-          <Value value="463"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="10">
-          <Value value="435"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="11">
-          <Value value="407"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="12">
-          <Value value="379"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="13">
-          <Value value="351"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="14">
-          <Value value="323"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="15">
-          <Value value="295"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="16">
-          <Value value="267"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="17">
-          <Value value="239"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="18">
-          <Value value="468"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="19">
-          <Value value="440"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="20">
-          <Value value="412"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="21">
-          <Value value="384"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="22">
-          <Value value="356"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="23">
-          <Value value="328"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="24">
-          <Value value="300"/>
-        </TopAccentAttachment>
-        <TopAccentAttachment index="25">
-          <Value value="272"/>
-        </TopAccentAttachment>
-      </MathTopAccentAttachment>
-      <ExtendedShapeCoverage Format="1">
-        <Glyph value="B"/>
-        <Glyph value="E"/>
-        <Glyph value="H"/>
-        <Glyph value="K"/>
-        <Glyph value="N"/>
-        <Glyph value="Q"/>
-        <Glyph value="T"/>
-        <Glyph value="W"/>
-        <Glyph value="Z"/>
-      </ExtendedShapeCoverage>
-      <MathKernInfo>
-        <MathKernCoverage Format="2">
-          <Glyph value="A"/>
-          <Glyph value="B"/>
-          <Glyph value="C"/>
-          <Glyph value="D"/>
-          <Glyph value="E"/>
-          <Glyph value="F"/>
-          <Glyph value="G"/>
-          <Glyph value="H"/>
-          <Glyph value="I"/>
-          <Glyph value="J"/>
-          <Glyph value="K"/>
-          <Glyph value="L"/>
-          <Glyph value="M"/>
-          <Glyph value="N"/>
-          <Glyph value="O"/>
-          <Glyph value="P"/>
-          <Glyph value="Q"/>
-          <Glyph value="R"/>
-          <Glyph value="S"/>
-          <Glyph value="T"/>
-          <Glyph value="U"/>
-          <Glyph value="V"/>
-          <Glyph value="W"/>
-          <Glyph value="X"/>
-          <Glyph value="Y"/>
-          <Glyph value="Z"/>
-        </MathKernCoverage>
-        <!-- MathKernCount=26 -->
-        <MathKernInfoRecords index="0">
-          <TopLeftMathKern>
-            <!-- HeightCount=5 -->
-            <CorrectionHeight index="0">
-              <Value value="12"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="19"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="40"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="17"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="45"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="52"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="31"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="57"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="83"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="109"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="135"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="161"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="187"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="213"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="239"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="29"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="48"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="67"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="86"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="105"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="124"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="143"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="162"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="181"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="200"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="1">
-          <TopRightMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="30"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="55"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="52"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="13"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="37"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="18"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="42"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="66"/>
-            </KernValue>
-          </TopLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="2">
-          <TopRightMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="31"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="57"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="83"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="55"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="70"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="14"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="50"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="19"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="37"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="55"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="64"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="82"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="27"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="44"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="61"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="31"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="3">
-          <TopRightMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="86"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="113"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="42"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="74"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="90"/>
-            </KernValue>
-          </TopRightMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="24"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="43"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="62"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="64"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="82"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="4">
-          <TopRightMathKern>
-            <!-- HeightCount=5 -->
-            <CorrectionHeight index="0">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="61"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="89"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="117"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="145"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="27"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="44"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="61"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="78"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="95"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="112"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="16"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="27"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="38"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="49"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="60"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="71"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="82"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="93"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="104"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="21"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="32"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="43"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="54"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="65"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="76"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="87"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="98"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="109"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="120"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="12"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="19"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="16"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="28"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="5">
-          <BottomRightMathKern>
-            <!-- HeightCount=5 -->
-            <CorrectionHeight index="0">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="47"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="89"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="110"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="90"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="110"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="130"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="6">
-          <TopRightMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="12"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="19"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="40"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="47"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="54"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="29"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="48"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="67"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="86"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="105"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="124"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="143"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="162"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="23"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="27"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="49"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="71"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="93"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="115"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="137"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="115"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="136"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="157"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="14"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="18"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="42"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="50"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="7">
-          <TopRightMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="13"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="37"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="61"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="69"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="90"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="110"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="130"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="150"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="170"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="190"/>
-            </KernValue>
-          </TopRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="8">
-          <TopRightMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="14"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="50"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="77"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="86"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="115"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="136"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="157"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="178"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="199"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="220"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="20"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="35"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="55"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="77"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="101"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="125"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="149"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="173"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="197"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="16"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="64"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="16"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="27"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="38"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="49"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="60"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="71"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="60"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="80"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="9">
-          <TopLeftMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="37"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="42"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="74"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="30"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="55"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="80"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="105"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="130"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="155"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="180"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="205"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="230"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="17"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="45"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="59"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="66"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="80"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="10">
-          <TopLeftMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="22"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="39"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="56"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="73"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="27"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="44"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="61"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="78"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="95"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="18"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="31"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="44"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="57"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="70"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="83"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="96"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="109"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="82"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="106"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="118"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="11">
-          <TopRightMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="17"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="17"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="24"/>
-            </KernValue>
-          </TopRightMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="19"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="12">
-          <TopRightMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="18"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="31"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="18"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="34"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="24"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="43"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="62"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="81"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="100"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="119"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="29"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="48"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="67"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="86"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="105"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="124"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="143"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="30"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="13">
-          <TopRightMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="19"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="47"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="19"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="37"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="46"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="25"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="65"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="85"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="105"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="125"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="145"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="90"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="110"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="130"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="150"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="170"/>
-            </KernValue>
-          </TopLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="14">
-          <TopRightMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="20"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="35"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="50"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="65"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="60"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="47"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="89"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="110"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="131"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="152"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="173"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="115"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="136"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="157"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="178"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="199"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="12"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="19"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="58"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="22"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="42"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="15">
-          <BottomRightMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="13"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="37"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="23"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="36"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="49"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="62"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="75"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="16">
-          <TopRightMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="22"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="39"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="56"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="73"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="90"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="107"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="82"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="94"/>
-            </KernValue>
-          </TopRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="24"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="43"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="62"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="64"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="82"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="17">
-          <TopRightMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="77"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="95"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="113"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="131"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="23"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="36"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="49"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="62"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="75"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="88"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="101"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="114"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="17"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=6 -->
-            <CorrectionHeight index="0">
-              <Value value="15"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="25"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="35"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="55"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="65"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="55"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="85"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="100"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="115"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="18">
-          <TopRightMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="24"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="43"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="62"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="81"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="100"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="119"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="138"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="157"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="66"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="80"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="108"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="122"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="136"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="30"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="18"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="26"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="16"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="27"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="38"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="49"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="60"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="71"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="82"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="26"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="42"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="74"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="90"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="106"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="122"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="138"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=5 -->
-            <CorrectionHeight index="0">
-              <Value value="26"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="47"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="89"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="110"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="90"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="110"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="130"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="19">
-          <TopRightMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="25"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="65"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="85"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="105"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="125"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="145"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="165"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="185"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="55"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="85"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="100"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="115"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="130"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="145"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="160"/>
-            </KernValue>
-          </TopRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="20">
-          <TopLeftMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="86"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="50"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="18"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="31"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="44"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="57"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="70"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="83"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="96"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="109"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="122"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="64"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="82"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="100"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="118"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="136"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="154"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="172"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="190"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="28"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="51"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="74"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="97"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="120"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="143"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="166"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="15"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="35"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="45"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="50"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="21">
-          <TopRightMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="27"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=4 -->
-            <CorrectionHeight index="0">
-              <Value value="33"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="61"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="89"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="117"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="21"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="32"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="43"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="54"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="65"/>
-            </KernValue>
-          </TopLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="22">
-          <TopRightMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="28"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="28"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="46"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=5 -->
-            <CorrectionHeight index="0">
-              <Value value="34"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="63"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="92"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="121"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="150"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="22"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="34"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="46"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="58"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="82"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=9 -->
-            <CorrectionHeight index="0">
-              <Value value="30"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="55"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="80"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="105"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="130"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="155"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="180"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="205"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="8">
-              <Value value="230"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="17"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="45"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="59"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="66"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="73"/>
-            </KernValue>
-            <KernValue index="9">
-              <Value value="80"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="23">
-          <TopRightMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="29"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="48"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="67"/>
-            </KernValue>
-          </TopRightMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=1 -->
-            <CorrectionHeight index="0">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="31"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="52"/>
-            </KernValue>
-          </BottomRightMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="24">
-          <TopRightMathKern>
-            <!-- HeightCount=3 -->
-            <CorrectionHeight index="0">
-              <Value value="30"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="55"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="80"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="30"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="50"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="90"/>
-            </KernValue>
-          </TopRightMathKern>
-          <TopLeftMathKern>
-            <!-- HeightCount=7 -->
-            <CorrectionHeight index="0">
-              <Value value="13"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="21"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="29"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="37"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="45"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="53"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="61"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="24"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="38"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="52"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="66"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="80"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="94"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="108"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="122"/>
-            </KernValue>
-          </TopLeftMathKern>
-          <BottomRightMathKern>
-            <!-- HeightCount=2 -->
-            <CorrectionHeight index="0">
-              <Value value="22"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="39"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="15"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="20"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="25"/>
-            </KernValue>
-          </BottomRightMathKern>
-          <BottomLeftMathKern>
-            <!-- HeightCount=0 -->
-            <KernValue index="0">
-              <Value value="19"/>
-            </KernValue>
-          </BottomLeftMathKern>
-        </MathKernInfoRecords>
-        <MathKernInfoRecords index="25">
-          <TopLeftMathKern>
-            <!-- HeightCount=8 -->
-            <CorrectionHeight index="0">
-              <Value value="14"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="1">
-              <Value value="23"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="2">
-              <Value value="32"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="3">
-              <Value value="41"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="4">
-              <Value value="50"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="5">
-              <Value value="59"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="6">
-              <Value value="68"/>
-            </CorrectionHeight>
-            <CorrectionHeight index="7">
-              <Value value="77"/>
-            </CorrectionHeight>
-            <KernValue index="0">
-              <Value value="25"/>
-            </KernValue>
-            <KernValue index="1">
-              <Value value="40"/>
-            </KernValue>
-            <KernValue index="2">
-              <Value value="55"/>
-            </KernValue>
-            <KernValue index="3">
-              <Value value="70"/>
-            </KernValue>
-            <KernValue index="4">
-              <Value value="85"/>
-            </KernValue>
-            <KernValue index="5">
-              <Value value="100"/>
-            </KernValue>
-            <KernValue index="6">
-              <Value value="115"/>
-            </KernValue>
-            <KernValue index="7">
-              <Value value="130"/>
-            </KernValue>
-            <KernValue index="8">
-              <Value value="145"/>
-            </KernValue>
-          </TopLeftMathKern>
-        </MathKernInfoRecords>
-      </MathKernInfo>
-    </MathGlyphInfo>
-    <MathVariants>
-      <MinConnectorOverlap value="54"/>
-      <VertGlyphCoverage Format="1">
-        <Glyph value="arrowup"/>
-        <Glyph value="arrowdown"/>
-        <Glyph value="arrowupdn"/>
-        <Glyph value="uni21A5"/>
-        <Glyph value="uni21A7"/>
-        <Glyph value="uni21C8"/>
-        <Glyph value="uni21CA"/>
-        <Glyph value="arrowdblup"/>
-        <Glyph value="arrowdbldown"/>
-        <Glyph value="uni21D5"/>
-        <Glyph value="uni21E7"/>
-        <Glyph value="uni21E9"/>
-      </VertGlyphCoverage>
-      <HorizGlyphCoverage Format="1">
-        <Glyph value="arrowleft"/>
-        <Glyph value="arrowright"/>
-        <Glyph value="arrowboth"/>
-        <Glyph value="uni21A4"/>
-        <Glyph value="uni21A6"/>
-        <Glyph value="uni21C7"/>
-        <Glyph value="uni21C9"/>
-        <Glyph value="arrowdblleft"/>
-        <Glyph value="arrowdblright"/>
-        <Glyph value="arrowdblboth"/>
-        <Glyph value="uni21E6"/>
-        <Glyph value="uni21E8"/>
-      </HorizGlyphCoverage>
-      <!-- VertGlyphCount=12 -->
-      <!-- HorizGlyphCount=12 -->
-      <VertGlyphConstruction index="0">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="331"/>
-          </ItalicsCorrection>
-          <!-- PartCount=2 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=4 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni2191_size2"/>
-          <AdvanceMeasurement value="2251"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni2191_size3"/>
-          <AdvanceMeasurement value="2501"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni2191_size4"/>
-          <AdvanceMeasurement value="3001"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni2191_size5"/>
-          <AdvanceMeasurement value="3751"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="1">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="237"/>
-          </ItalicsCorrection>
-          <!-- PartCount=5 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="top"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=6 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni2193_size2"/>
-          <AdvanceMeasurement value="2451"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni2193_size3"/>
-          <AdvanceMeasurement value="2701"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni2193_size4"/>
-          <AdvanceMeasurement value="3201"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni2193_size5"/>
-          <AdvanceMeasurement value="3951"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni2193_size6"/>
-          <AdvanceMeasurement value="4201"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="5">
-          <VariantGlyph value="uni2193_size7"/>
-          <AdvanceMeasurement value="4701"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="2">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="143"/>
-          </ItalicsCorrection>
-          <!-- PartCount=9 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="top"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=1 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni2195_size2"/>
-          <AdvanceMeasurement value="2651"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="3">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="438"/>
-          </ItalicsCorrection>
-          <!-- PartCount=9 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="top"/>
-            <StartConnectorLength value="262"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=3 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21A5_size2"/>
-          <AdvanceMeasurement value="2351"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21A5_size3"/>
-          <AdvanceMeasurement value="2601"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21A5_size4"/>
-          <AdvanceMeasurement value="3101"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="4">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="344"/>
-          </ItalicsCorrection>
-          <!-- PartCount=13 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="9">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="10">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="11">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="12">
-            <glyph value="top"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=5 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21A7_size2"/>
-          <AdvanceMeasurement value="2551"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21A7_size3"/>
-          <AdvanceMeasurement value="2801"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21A7_size4"/>
-          <AdvanceMeasurement value="3301"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21A7_size5"/>
-          <AdvanceMeasurement value="4051"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21A7_size6"/>
-          <AdvanceMeasurement value="4301"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="5">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="189"/>
-          </ItalicsCorrection>
-          <!-- PartCount=1 -->
-          <PartRecords index="0">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=3 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21C8_size2"/>
-          <AdvanceMeasurement value="2051"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21C8_size3"/>
-          <AdvanceMeasurement value="2301"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21C8_size4"/>
-          <AdvanceMeasurement value="2801"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="6">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="444"/>
-          </ItalicsCorrection>
-          <!-- PartCount=3 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="top"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=5 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21CA_size2"/>
-          <AdvanceMeasurement value="2251"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21CA_size3"/>
-          <AdvanceMeasurement value="2501"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21CA_size4"/>
-          <AdvanceMeasurement value="3001"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21CA_size5"/>
-          <AdvanceMeasurement value="3751"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21CA_size6"/>
-          <AdvanceMeasurement value="4001"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="7">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="115"/>
-          </ItalicsCorrection>
-          <!-- PartCount=2 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=5 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21D1_size2"/>
-          <AdvanceMeasurement value="2951"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21D1_size3"/>
-          <AdvanceMeasurement value="3201"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21D1_size4"/>
-          <AdvanceMeasurement value="3701"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21D1_size5"/>
-          <AdvanceMeasurement value="4451"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21D1_size6"/>
-          <AdvanceMeasurement value="4701"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="8">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="370"/>
-          </ItalicsCorrection>
-          <!-- PartCount=5 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="top"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=0 -->
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="9">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="276"/>
-          </ItalicsCorrection>
-          <!-- PartCount=9 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="top"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=2 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21D5_size2"/>
-          <AdvanceMeasurement value="3351"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21D5_size3"/>
-          <AdvanceMeasurement value="3601"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="10">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="128"/>
-          </ItalicsCorrection>
-          <!-- PartCount=13 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="9">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="10">
-            <glyph value="center"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="11">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="12">
-            <glyph value="top"/>
-            <StartConnectorLength value="262"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=6 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21E7_size2"/>
-          <AdvanceMeasurement value="3251"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21E7_size3"/>
-          <AdvanceMeasurement value="3501"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21E7_size4"/>
-          <AdvanceMeasurement value="4001"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21E7_size5"/>
-          <AdvanceMeasurement value="4751"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21E7_size6"/>
-          <AdvanceMeasurement value="5001"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="5">
-          <VariantGlyph value="uni21E7_size7"/>
-          <AdvanceMeasurement value="5501"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <VertGlyphConstruction index="11">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="383"/>
-          </ItalicsCorrection>
-          <!-- PartCount=2 -->
-          <PartRecords index="0">
-            <glyph value="bottom"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="vertical"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="54"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=1 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21E9_size2"/>
-          <AdvanceMeasurement value="3451"/>
-        </MathGlyphVariantRecord>
-      </VertGlyphConstruction>
-      <HorizGlyphConstruction index="0">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="124"/>
-          </ItalicsCorrection>
-          <!-- PartCount=1 -->
-          <PartRecords index="0">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=3 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni2190_size2"/>
-          <AdvanceMeasurement value="2151"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni2190_size3"/>
-          <AdvanceMeasurement value="2401"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni2190_size4"/>
-          <AdvanceMeasurement value="2901"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="1">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="379"/>
-          </ItalicsCorrection>
-          <!-- PartCount=3 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="262"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="right"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=5 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni2192_size2"/>
-          <AdvanceMeasurement value="2351"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni2192_size3"/>
-          <AdvanceMeasurement value="2601"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni2192_size4"/>
-          <AdvanceMeasurement value="3101"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni2192_size5"/>
-          <AdvanceMeasurement value="3851"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni2192_size6"/>
-          <AdvanceMeasurement value="4101"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="2">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="285"/>
-          </ItalicsCorrection>
-          <!-- PartCount=7 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="123"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="365"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="right"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=0 -->
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="3">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="231"/>
-          </ItalicsCorrection>
-          <!-- PartCount=7 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="right"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=2 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21A4_size2"/>
-          <AdvanceMeasurement value="2251"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21A4_size3"/>
-          <AdvanceMeasurement value="2501"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="4">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="137"/>
-          </ItalicsCorrection>
-          <!-- PartCount=11 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="9">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="10">
-            <glyph value="right"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=4 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21A6_size2"/>
-          <AdvanceMeasurement value="2451"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21A6_size3"/>
-          <AdvanceMeasurement value="2701"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21A6_size4"/>
-          <AdvanceMeasurement value="3201"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21A6_size5"/>
-          <AdvanceMeasurement value="3951"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="5">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="331"/>
-          </ItalicsCorrection>
-          <!-- PartCount=13 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="9">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="10">
-            <glyph value="center"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="11">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="123"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="12">
-            <glyph value="right"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=2 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21C7_size2"/>
-          <AdvanceMeasurement value="1951"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21C7_size3"/>
-          <AdvanceMeasurement value="2201"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="6">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="237"/>
-          </ItalicsCorrection>
-          <!-- PartCount=2 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="262"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=4 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21C9_size2"/>
-          <AdvanceMeasurement value="2151"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21C9_size3"/>
-          <AdvanceMeasurement value="2401"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21C9_size4"/>
-          <AdvanceMeasurement value="2901"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21C9_size5"/>
-          <AdvanceMeasurement value="3651"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="7">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="257"/>
-          </ItalicsCorrection>
-          <!-- PartCount=1 -->
-          <PartRecords index="0">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=4 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21D0_size2"/>
-          <AdvanceMeasurement value="2851"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21D0_size3"/>
-          <AdvanceMeasurement value="3101"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21D0_size4"/>
-          <AdvanceMeasurement value="3601"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21D0_size5"/>
-          <AdvanceMeasurement value="4351"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="8">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="163"/>
-          </ItalicsCorrection>
-          <!-- PartCount=3 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="262"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="right"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="296"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=6 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21D2_size2"/>
-          <AdvanceMeasurement value="3051"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21D2_size3"/>
-          <AdvanceMeasurement value="3301"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21D2_size4"/>
-          <AdvanceMeasurement value="3801"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21D2_size5"/>
-          <AdvanceMeasurement value="4551"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21D2_size6"/>
-          <AdvanceMeasurement value="4801"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="5">
-          <VariantGlyph value="uni21D2_size7"/>
-          <AdvanceMeasurement value="5301"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="9">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="418"/>
-          </ItalicsCorrection>
-          <!-- PartCount=7 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="262"/>
-            <EndConnectorLength value="400"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="89"/>
-            <EndConnectorLength value="192"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="54"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="right"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="227"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=1 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21D4_size2"/>
-          <AdvanceMeasurement value="3251"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="10">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="270"/>
-          </ItalicsCorrection>
-          <!-- PartCount=11 -->
-          <PartRecords index="0">
-            <glyph value="left"/>
-            <StartConnectorLength value="158"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="1">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="400"/>
-            <EndConnectorLength value="158"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="2">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="3">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="4">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="5">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="6">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="7">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="8">
-            <glyph value="center"/>
-            <StartConnectorLength value="227"/>
-            <EndConnectorLength value="331"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-          <PartRecords index="9">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="192"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-          <PartRecords index="10">
-            <glyph value="right"/>
-            <StartConnectorLength value="296"/>
-            <EndConnectorLength value="365"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="0"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=5 -->
-        <MathGlyphVariantRecord index="0">
-          <VariantGlyph value="uni21E6_size2"/>
-          <AdvanceMeasurement value="3151"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="1">
-          <VariantGlyph value="uni21E6_size3"/>
-          <AdvanceMeasurement value="3401"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="2">
-          <VariantGlyph value="uni21E6_size4"/>
-          <AdvanceMeasurement value="3901"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="3">
-          <VariantGlyph value="uni21E6_size5"/>
-          <AdvanceMeasurement value="4651"/>
-        </MathGlyphVariantRecord>
-        <MathGlyphVariantRecord index="4">
-          <VariantGlyph value="uni21E6_size6"/>
-          <AdvanceMeasurement value="4901"/>
-        </MathGlyphVariantRecord>
-      </HorizGlyphConstruction>
-      <HorizGlyphConstruction index="11">
-        <GlyphAssembly>
-          <ItalicsCorrection>
-            <Value value="176"/>
-          </ItalicsCorrection>
-          <!-- PartCount=1 -->
-          <PartRecords index="0">
-            <glyph value="horizontal"/>
-            <StartConnectorLength value="331"/>
-            <EndConnectorLength value="89"/>
-            <FullAdvance value="1000"/>
-            <PartFlags value="1"/>
-          </PartRecords>
-        </GlyphAssembly>
-        <!-- VariantCount=0 -->
-      </HorizGlyphConstruction>
-    </MathVariants>
-  </MATH>
-
-  <hmtx>
-    <mtx name=".notdef" width="1000" lsb="0"/>
-    <mtx name="A" width="1000" lsb="0"/>
-    <mtx name="B" width="1000" lsb="0"/>
-    <mtx name="C" width="1000" lsb="0"/>
-    <mtx name="D" width="1000" lsb="0"/>
-    <mtx name="E" width="1000" lsb="0"/>
-    <mtx name="F" width="1000" lsb="0"/>
-    <mtx name="G" width="1000" lsb="0"/>
-    <mtx name="H" width="1000" lsb="0"/>
-    <mtx name="I" width="1000" lsb="0"/>
-    <mtx name="J" width="1000" lsb="0"/>
-    <mtx name="K" width="1000" lsb="0"/>
-    <mtx name="L" width="1000" lsb="0"/>
-    <mtx name="M" width="1000" lsb="0"/>
-    <mtx name="N" width="1000" lsb="0"/>
-    <mtx name="O" width="1000" lsb="0"/>
-    <mtx name="P" width="1000" lsb="0"/>
-    <mtx name="Q" width="1000" lsb="0"/>
-    <mtx name="R" width="1000" lsb="0"/>
-    <mtx name="S" width="1000" lsb="0"/>
-    <mtx name="T" width="1000" lsb="0"/>
-    <mtx name="U" width="1000" lsb="0"/>
-    <mtx name="V" width="1000" lsb="0"/>
-    <mtx name="W" width="1000" lsb="0"/>
-    <mtx name="X" width="1000" lsb="0"/>
-    <mtx name="Y" width="1000" lsb="0"/>
-    <mtx name="Z" width="1000" lsb="0"/>
-    <mtx name="arrowboth" width="1000" lsb="0"/>
-    <mtx name="arrowdblboth" width="1000" lsb="0"/>
-    <mtx name="arrowdbldown" width="1000" lsb="0"/>
-    <mtx name="arrowdblleft" width="1000" lsb="0"/>
-    <mtx name="arrowdblright" width="1000" lsb="0"/>
-    <mtx name="arrowdblup" width="1000" lsb="0"/>
-    <mtx name="arrowdown" width="1000" lsb="0"/>
-    <mtx name="arrowleft" width="1000" lsb="0"/>
-    <mtx name="arrowright" width="1000" lsb="0"/>
-    <mtx name="arrowup" width="1000" lsb="0"/>
-    <mtx name="arrowupdn" width="1000" lsb="0"/>
-    <mtx name="bottom" width="1000" lsb="0"/>
-    <mtx name="braceleft" width="1000" lsb="0"/>
-    <mtx name="center" width="1000" lsb="0"/>
-    <mtx name="horizontal" width="1000" lsb="0"/>
-    <mtx name="left" width="1000" lsb="0"/>
-    <mtx name="right" width="1000" lsb="0"/>
-    <mtx name="space" width="1000" lsb="0"/>
-    <mtx name="top" width="1000" lsb="0"/>
-    <mtx name="underscore" width="1000" lsb="0"/>
-    <mtx name="uni2190_size2" width="1000" lsb="0"/>
-    <mtx name="uni2190_size3" width="1000" lsb="0"/>
-    <mtx name="uni2190_size4" width="1000" lsb="0"/>
-    <mtx name="uni2191_size2" width="1000" lsb="0"/>
-    <mtx name="uni2191_size3" width="1000" lsb="0"/>
-    <mtx name="uni2191_size4" width="1000" lsb="0"/>
-    <mtx name="uni2191_size5" width="1000" lsb="0"/>
-    <mtx name="uni2192_size2" width="1000" lsb="0"/>
-    <mtx name="uni2192_size3" width="1000" lsb="0"/>
-    <mtx name="uni2192_size4" width="1000" lsb="0"/>
-    <mtx name="uni2192_size5" width="1000" lsb="0"/>
-    <mtx name="uni2192_size6" width="1000" lsb="0"/>
-    <mtx name="uni2193_size2" width="1000" lsb="0"/>
-    <mtx name="uni2193_size3" width="1000" lsb="0"/>
-    <mtx name="uni2193_size4" width="1000" lsb="0"/>
-    <mtx name="uni2193_size5" width="1000" lsb="0"/>
-    <mtx name="uni2193_size6" width="1000" lsb="0"/>
-    <mtx name="uni2193_size7" width="1000" lsb="0"/>
-    <mtx name="uni2195_size2" width="1000" lsb="0"/>
-    <mtx name="uni21A4" width="1000" lsb="0"/>
-    <mtx name="uni21A4_size2" width="1000" lsb="0"/>
-    <mtx name="uni21A4_size3" width="1000" lsb="0"/>
-    <mtx name="uni21A5" width="1000" lsb="0"/>
-    <mtx name="uni21A5_size2" width="1000" lsb="0"/>
-    <mtx name="uni21A5_size3" width="1000" lsb="0"/>
-    <mtx name="uni21A5_size4" width="1000" lsb="0"/>
-    <mtx name="uni21A6" width="1000" lsb="0"/>
-    <mtx name="uni21A6_size2" width="1000" lsb="0"/>
-    <mtx name="uni21A6_size3" width="1000" lsb="0"/>
-    <mtx name="uni21A6_size4" width="1000" lsb="0"/>
-    <mtx name="uni21A6_size5" width="1000" lsb="0"/>
-    <mtx name="uni21A7" width="1000" lsb="0"/>
-    <mtx name="uni21A7_size2" width="1000" lsb="0"/>
-    <mtx name="uni21A7_size3" width="1000" lsb="0"/>
-    <mtx name="uni21A7_size4" width="1000" lsb="0"/>
-    <mtx name="uni21A7_size5" width="1000" lsb="0"/>
-    <mtx name="uni21A7_size6" width="1000" lsb="0"/>
-    <mtx name="uni21C7" width="1000" lsb="0"/>
-    <mtx name="uni21C7_size2" width="1000" lsb="0"/>
-    <mtx name="uni21C7_size3" width="1000" lsb="0"/>
-    <mtx name="uni21C8" width="1000" lsb="0"/>
-    <mtx name="uni21C8_size2" width="1000" lsb="0"/>
-    <mtx name="uni21C8_size3" width="1000" lsb="0"/>
-    <mtx name="uni21C8_size4" width="1000" lsb="0"/>
-    <mtx name="uni21C9" width="1000" lsb="0"/>
-    <mtx name="uni21C9_size2" width="1000" lsb="0"/>
-    <mtx name="uni21C9_size3" width="1000" lsb="0"/>
-    <mtx name="uni21C9_size4" width="1000" lsb="0"/>
-    <mtx name="uni21C9_size5" width="1000" lsb="0"/>
-    <mtx name="uni21CA" width="1000" lsb="0"/>
-    <mtx name="uni21CA_size2" width="1000" lsb="0"/>
-    <mtx name="uni21CA_size3" width="1000" lsb="0"/>
-    <mtx name="uni21CA_size4" width="1000" lsb="0"/>
-    <mtx name="uni21CA_size5" width="1000" lsb="0"/>
-    <mtx name="uni21CA_size6" width="1000" lsb="0"/>
-    <mtx name="uni21D0_size2" width="1000" lsb="0"/>
-    <mtx name="uni21D0_size3" width="1000" lsb="0"/>
-    <mtx name="uni21D0_size4" width="1000" lsb="0"/>
-    <mtx name="uni21D0_size5" width="1000" lsb="0"/>
-    <mtx name="uni21D1_size2" width="1000" lsb="0"/>
-    <mtx name="uni21D1_size3" width="1000" lsb="0"/>
-    <mtx name="uni21D1_size4" width="1000" lsb="0"/>
-    <mtx name="uni21D1_size5" width="1000" lsb="0"/>
-    <mtx name="uni21D1_size6" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size2" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size3" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size4" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size5" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size6" width="1000" lsb="0"/>
-    <mtx name="uni21D2_size7" width="1000" lsb="0"/>
-    <mtx name="uni21D4_size2" width="1000" lsb="0"/>
-    <mtx name="uni21D5" width="1000" lsb="0"/>
-    <mtx name="uni21D5_size2" width="1000" lsb="0"/>
-    <mtx name="uni21D5_size3" width="1000" lsb="0"/>
-    <mtx name="uni21E6" width="1000" lsb="0"/>
-    <mtx name="uni21E6_size2" width="1000" lsb="0"/>
-    <mtx name="uni21E6_size3" width="1000" lsb="0"/>
-    <mtx name="uni21E6_size4" width="1000" lsb="0"/>
-    <mtx name="uni21E6_size5" width="1000" lsb="0"/>
-    <mtx name="uni21E6_size6" width="1000" lsb="0"/>
-    <mtx name="uni21E7" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size2" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size3" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size4" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size5" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size6" width="1000" lsb="0"/>
-    <mtx name="uni21E7_size7" width="1000" lsb="0"/>
-    <mtx name="uni21E8" width="1000" lsb="0"/>
-    <mtx name="uni21E9" width="1000" lsb="0"/>
-    <mtx name="uni21E9_size2" width="1000" lsb="0"/>
-    <mtx name="uni23A7" width="1000" lsb="0"/>
-    <mtx name="uni23A8" width="1000" lsb="0"/>
-    <mtx name="uni23A9" width="1000" lsb="0"/>
-    <mtx name="uni23AA" width="1000" lsb="0"/>
-    <mtx name="vertical" width="1000" lsb="400"/>
-  </hmtx>
-
-</ttFont>
index 7e7783c..4830c47 100644 (file)
@@ -1,3 +1,5 @@
 cmap-format12-only files created by ttx & remove all other cmap entries
 
 Inconsolata-Regular.abc.widerc.ttf has the hmtx width of "c" set to 600; everything else is 500. Subsetting out c should reduce numberOfHMetrics to 1.
+
+chromacheck-* fonts are from https://github.com/RoelN/ChromaCheck/tree/master/fonts and licensed under MIT by Roel Nieskens and Google.
diff --git a/test/api/fonts/Roboto-Regular.multihdmx.a.ttf b/test/api/fonts/Roboto-Regular.multihdmx.a.ttf
new file mode 100644 (file)
index 0000000..dd82178
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.multihdmx.a.ttf differ
diff --git a/test/api/fonts/Roboto-Regular.multihdmx.abc.ttf b/test/api/fonts/Roboto-Regular.multihdmx.abc.ttf
new file mode 100644 (file)
index 0000000..03dd8b6
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.multihdmx.abc.ttf differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf b/test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf
new file mode 100644 (file)
index 0000000..08bc0e0
Binary files /dev/null and b/test/api/fonts/SourceHanSans-Regular.41,3041,4C2E.otf differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.nohints.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nohints.otf
new file mode 100644 (file)
index 0000000..ec39590
Binary files /dev/null and b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nohints.otf differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf
new file mode 100644 (file)
index 0000000..00a112f
Binary files /dev/null and b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.otf
new file mode 100644 (file)
index 0000000..6fe9bf3
Binary files /dev/null and b/test/api/fonts/SourceHanSans-Regular.41,4C2E.nosubrs.otf differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.otf
new file mode 100644 (file)
index 0000000..2c6cd9a
Binary files /dev/null and b/test/api/fonts/SourceHanSans-Regular.41,4C2E.otf differ
diff --git a/test/api/fonts/SourceSansPro-Regular.abc.otf b/test/api/fonts/SourceSansPro-Regular.abc.otf
new file mode 100644 (file)
index 0000000..7f51bd3
Binary files /dev/null and b/test/api/fonts/SourceSansPro-Regular.abc.otf differ
diff --git a/test/api/fonts/SourceSansPro-Regular.ac.nohints.otf b/test/api/fonts/SourceSansPro-Regular.ac.nohints.otf
new file mode 100644 (file)
index 0000000..14a3a5f
Binary files /dev/null and b/test/api/fonts/SourceSansPro-Regular.ac.nohints.otf differ
diff --git a/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.nohints.otf b/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.nohints.otf
new file mode 100644 (file)
index 0000000..69e244c
Binary files /dev/null and b/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.nohints.otf differ
diff --git a/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.otf b/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.otf
new file mode 100644 (file)
index 0000000..28edf13
Binary files /dev/null and b/test/api/fonts/SourceSansPro-Regular.ac.nosubrs.otf differ
diff --git a/test/api/fonts/SourceSansPro-Regular.ac.otf b/test/api/fonts/SourceSansPro-Regular.ac.otf
new file mode 100644 (file)
index 0000000..12d6d0f
Binary files /dev/null and b/test/api/fonts/SourceSansPro-Regular.ac.otf differ
diff --git a/test/api/fonts/aat-feat.ttf b/test/api/fonts/aat-feat.ttf
new file mode 100644 (file)
index 0000000..1ff99a2
Binary files /dev/null and b/test/api/fonts/aat-feat.ttf differ
diff --git a/test/api/fonts/aat-morx.ttf b/test/api/fonts/aat-morx.ttf
new file mode 100644 (file)
index 0000000..5827ec5
Binary files /dev/null and b/test/api/fonts/aat-morx.ttf differ
diff --git a/test/api/fonts/aat-trak.ttf b/test/api/fonts/aat-trak.ttf
new file mode 100644 (file)
index 0000000..07ae3af
Binary files /dev/null and b/test/api/fonts/aat-trak.ttf differ
diff --git a/test/api/fonts/base.ttf b/test/api/fonts/base.ttf
new file mode 100644 (file)
index 0000000..d984966
Binary files /dev/null and b/test/api/fonts/base.ttf differ
diff --git a/test/api/fonts/cff1_dotsect.nohints.otf b/test/api/fonts/cff1_dotsect.nohints.otf
new file mode 100644 (file)
index 0000000..faa932e
Binary files /dev/null and b/test/api/fonts/cff1_dotsect.nohints.otf differ
diff --git a/test/api/fonts/cff1_dotsect.otf b/test/api/fonts/cff1_dotsect.otf
new file mode 100644 (file)
index 0000000..dabd4b3
Binary files /dev/null and b/test/api/fonts/cff1_dotsect.otf differ
diff --git a/test/api/fonts/cff1_expert.2D,F6E9,FB00.otf b/test/api/fonts/cff1_expert.2D,F6E9,FB00.otf
new file mode 100644 (file)
index 0000000..8c198b7
Binary files /dev/null and b/test/api/fonts/cff1_expert.2D,F6E9,FB00.otf differ
diff --git a/test/api/fonts/cff1_expert.otf b/test/api/fonts/cff1_expert.otf
new file mode 100644 (file)
index 0000000..970ed67
Binary files /dev/null and b/test/api/fonts/cff1_expert.otf differ
diff --git a/test/api/fonts/cff1_flex.otf b/test/api/fonts/cff1_flex.otf
new file mode 100644 (file)
index 0000000..1ef59e1
Binary files /dev/null and b/test/api/fonts/cff1_flex.otf differ
diff --git a/test/api/fonts/cff1_seac.C0.otf b/test/api/fonts/cff1_seac.C0.otf
new file mode 100644 (file)
index 0000000..aed2fdd
Binary files /dev/null and b/test/api/fonts/cff1_seac.C0.otf differ
diff --git a/test/api/fonts/cff1_seac.otf b/test/api/fonts/cff1_seac.otf
new file mode 100644 (file)
index 0000000..bc7991c
Binary files /dev/null and b/test/api/fonts/cff1_seac.otf differ
diff --git a/test/api/fonts/chromacheck-cbdt.ttf b/test/api/fonts/chromacheck-cbdt.ttf
new file mode 100644 (file)
index 0000000..100c01a
Binary files /dev/null and b/test/api/fonts/chromacheck-cbdt.ttf differ
diff --git a/test/api/fonts/chromacheck-colr.ttf b/test/api/fonts/chromacheck-colr.ttf
new file mode 100644 (file)
index 0000000..626809c
Binary files /dev/null and b/test/api/fonts/chromacheck-colr.ttf differ
diff --git a/test/api/fonts/chromacheck-sbix.ttf b/test/api/fonts/chromacheck-sbix.ttf
new file mode 100644 (file)
index 0000000..b6f1fe9
Binary files /dev/null and b/test/api/fonts/chromacheck-sbix.ttf differ
diff --git a/test/api/fonts/chromacheck-svg.ttf b/test/api/fonts/chromacheck-svg.ttf
new file mode 100644 (file)
index 0000000..d39cc56
Binary files /dev/null and b/test/api/fonts/chromacheck-svg.ttf differ
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5658272078495744 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5658272078495744
new file mode 100644 (file)
index 0000000..f3fa938
Binary files /dev/null and b/test/api/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5658272078495744 differ
diff --git a/test/api/fonts/cv01.otf b/test/api/fonts/cv01.otf
new file mode 100644 (file)
index 0000000..01dbf01
Binary files /dev/null and b/test/api/fonts/cv01.otf differ
diff --git a/test/api/fonts/lcar.ttf b/test/api/fonts/lcar.ttf
new file mode 100644 (file)
index 0000000..4d17663
Binary files /dev/null and b/test/api/fonts/lcar.ttf differ
index c34f394..cefa4e0 100644 (file)
@@ -47,18 +47,6 @@ typedef short bool;
 
 HB_BEGIN_DECLS
 
-static inline hb_face_t *
-hb_subset_test_open_font (const char *font_path)
-{
-#if GLIB_CHECK_VERSION(2,37,2)
-  char* path = g_test_build_filename(G_TEST_DIST, font_path, NULL);
-#else
-  char* path = g_strdup(font_path);
-#endif
-
-  return hb_face_create (hb_blob_create_from_file (path), 0);
-}
-
 static inline hb_subset_input_t *
 hb_subset_test_create_input(const hb_set_t  *codepoints)
 {
@@ -72,11 +60,9 @@ static inline hb_face_t *
 hb_subset_test_create_subset (hb_face_t *source,
                               hb_subset_input_t *input)
 {
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (source, profile, input);
+  hb_face_t *subset = hb_subset (source, input);
   g_assert (subset);
 
-  hb_subset_profile_destroy (profile);
   hb_subset_input_destroy (input);
   return subset;
 }
@@ -87,7 +73,7 @@ hb_subset_test_check (hb_face_t *expected,
                       hb_tag_t   table)
 {
   hb_blob_t *expected_blob, *actual_blob;
-  fprintf(stderr, "compare %c%c%c%c\n", HB_UNTAG(table));
+  //fprintf(stderr, "comparing %c%c%c%c ", HB_UNTAG(table));
   expected_blob = hb_face_reference_table (expected, table);
   actual_blob = hb_face_reference_table (actual, table);
   hb_test_assert_blobs_equal (expected_blob, actual_blob);
index 307845f..872f45c 100644 (file)
@@ -42,6 +42,7 @@ HB_BEGIN_DECLS
 /* Just in case */
 #undef G_DISABLE_ASSERT
 
+#define HB_UNUSED      G_GNUC_UNUSED
 
 /* Misc */
 
@@ -276,6 +277,28 @@ G_STMT_START { \
 } G_STMT_END
 
 
+static inline hb_face_t *
+hb_test_open_font_file (const char *font_path)
+{
+#if GLIB_CHECK_VERSION(2,37,2)
+  char *path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
+#else
+  char *path = g_strdup (font_path);
+#endif
+
+  hb_blob_t *blob = hb_blob_create_from_file (path);
+  hb_face_t *face;
+  if (hb_blob_get_length (blob) == 0)
+    g_error ("Font %s not found.", path);
+
+  face = hb_face_create (blob, 0);
+  hb_blob_destroy (blob);
+
+  g_free (path);
+
+  return face;
+}
+
 HB_END_DECLS
 
 #endif /* HB_TEST_H */
diff --git a/test/api/test-aat-layout.c b/test/api/test-aat-layout.c
new file mode 100644 (file)
index 0000000..1384556
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "hb-test.h"
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-aat.h>
+
+/* Unit tests for hb-aat.h */
+
+static hb_face_t *face;
+static hb_face_t *sbix;
+
+static void
+test_aat_get_feature_types (void)
+{
+  hb_aat_layout_feature_type_t features[3];
+  unsigned int count = 3;
+  g_assert_cmpuint (11, ==, hb_aat_layout_get_feature_types (face, 0, &count, features));
+
+  g_assert_cmpuint (1, ==, features[0]);
+  g_assert_cmpuint (3, ==, features[1]);
+  g_assert_cmpuint (6, ==, features[2]);
+
+  g_assert_cmpuint (258, ==, hb_aat_layout_feature_type_get_name_id (face, features[0]));
+  g_assert_cmpuint (261, ==, hb_aat_layout_feature_type_get_name_id (face, features[1]));
+  g_assert_cmpuint (265, ==, hb_aat_layout_feature_type_get_name_id (face, features[2]));
+}
+
+static void
+test_aat_get_feature_selectors (void)
+{
+  unsigned int default_index;
+  hb_aat_layout_feature_selector_info_t settings[3];
+  unsigned int count = 3;
+
+  g_assert_cmpuint (4, ==, hb_aat_layout_feature_type_get_selector_infos (face,
+                                                                         HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE,
+                                                                         0, &count, settings,
+                                                                         &default_index));
+  g_assert_cmpuint (3, ==, count);
+  g_assert_cmpuint (0, ==, default_index);
+
+  g_assert_cmpuint (0, ==, settings[0].enable);
+  g_assert_cmpuint (294, ==, settings[0].name_id);
+
+  g_assert_cmpuint (1, ==, settings[1].enable);
+  g_assert_cmpuint (295, ==, settings[1].name_id);
+
+  g_assert_cmpuint (2, ==, settings[2].enable);
+  g_assert_cmpuint (296, ==, settings[2].name_id);
+
+  count = 3;
+  g_assert_cmpuint (4, ==, hb_aat_layout_feature_type_get_selector_infos (face,
+                                                                         HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE,
+                                                                         3, &count, settings,
+                                                                         &default_index));
+  g_assert_cmpuint (1, ==, count);
+  g_assert_cmpuint (0, ==, default_index);
+
+  g_assert_cmpuint (3, ==, settings[0].enable);
+  g_assert_cmpuint (297, ==, settings[0].name_id);
+
+  count = 1;
+  g_assert_cmpuint (1, ==, hb_aat_layout_feature_type_get_selector_infos (face,
+                                                                         HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,
+                                                                         0, &count, settings,
+                                                                         &default_index));
+  g_assert_cmpuint (1, ==, count);
+  g_assert_cmpuint (HB_AAT_LAYOUT_NO_SELECTOR_INDEX, ==, default_index);
+
+  g_assert_cmpuint (8, ==, settings[0].enable);
+  g_assert_cmpuint (308, ==, settings[0].name_id);
+
+  count = 100;
+  g_assert_cmpuint (0, ==, hb_aat_layout_feature_type_get_selector_infos (face, HB_AAT_LAYOUT_FEATURE_TYPE_INVALID,
+                                                                         0, &count, settings,
+                                                                         NULL));
+  g_assert_cmpuint (0, ==, count);
+}
+
+static void
+test_aat_has (void)
+{
+  hb_face_t *morx = hb_test_open_font_file ("fonts/aat-morx.ttf");
+  hb_face_t *trak;
+  g_assert (hb_aat_layout_has_substitution (morx));
+  hb_face_destroy (morx);
+
+  trak = hb_test_open_font_file ("fonts/aat-trak.ttf");
+  g_assert (hb_aat_layout_has_tracking (trak));
+  hb_face_destroy (trak);
+}
+
+int
+main (int argc, char **argv)
+{
+  unsigned int status;
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_aat_get_feature_types);
+  hb_test_add (test_aat_get_feature_selectors);
+  hb_test_add (test_aat_has);
+
+  face = hb_test_open_font_file ("fonts/aat-feat.ttf");
+  sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf");
+  status = hb_test_run ();
+  hb_face_destroy (sbix);
+  hb_face_destroy (face);
+  return status;
+}
diff --git a/test/api/test-baseline.c b/test/api/test-baseline.c
new file mode 100644 (file)
index 0000000..a120e14
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#include "hb-test.h"
+
+#include <hb-ot.h>
+
+/* Unit tests for hb-ot-layout.h baseline */
+
+static void
+test_ot_layout_base (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/base.ttf");
+  hb_font_t *font = hb_font_create (face);
+
+#if 0
+  hb_position_t position;
+  g_assert (hb_ot_layout_get_baseline (font, HB_OT_LAYOUT_BASELINE_ICFB, HB_DIRECTION_TTB,
+                                      HB_TAG ('h','a','n','i'),
+                                      HB_TAG ('E','N','G',' '),
+                                      &position));
+  g_assert_cmpint (46, ==, position);
+#endif
+
+  hb_font_destroy (font);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_ot_layout_base);
+
+  return hb_test_run();
+}
index d566f4e..7914a26 100644 (file)
@@ -195,7 +195,7 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
 }
 
 static void
-fixture_finish (fixture_t *fixture, gconstpointer user_data)
+fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
 {
   hb_blob_destroy (fixture->blob);
   g_assert_cmpint (fixture->freed, ==, 1);
index 5c98a9a..64ab3db 100644 (file)
@@ -92,14 +92,14 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
 }
 
 static void
-fixture_finish (fixture_t *fixture, gconstpointer user_data)
+fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
 {
   hb_buffer_destroy (fixture->buffer);
 }
 
 
 static void
-test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
+test_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
 {
   hb_buffer_t *b = fixture->buffer;
   hb_unicode_funcs_t *ufuncs;
@@ -294,7 +294,7 @@ test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
 }
 
 static void
-test_buffer_positions (fixture_t *fixture, gconstpointer user_data)
+test_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
 {
   hb_buffer_t *b = fixture->buffer;
   unsigned int i, len, len2;
@@ -319,7 +319,7 @@ test_buffer_positions (fixture_t *fixture, gconstpointer user_data)
 }
 
 static void
-test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
+test_buffer_allocation (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
 {
   hb_buffer_t *b = fixture->buffer;
 
@@ -379,14 +379,15 @@ static void
 test_buffer_utf8_conversion (void)
 {
   hb_buffer_t *b;
-  hb_glyph_info_t *glyphs;
-  unsigned int bytes, chars, i, j, len;
+  unsigned int chars, i, j, len;
 
   b = hb_buffer_create ();
   hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
 
   for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++)
   {
+    unsigned int bytes;
+    hb_glyph_info_t *glyphs;
     const utf8_conversion_test_t *test = &utf8_conversion_tests[i];
     char *escaped;
 
index 4b43b83..b4518ad 100644 (file)
@@ -32,6 +32,8 @@
 #endif
 
 #include <hb.h>
+#include <hb-ot.h>
+#include <hb-aat.h>
 
 #ifdef HAVE_GLIB
 #include <hb-glib.h>
 #include <hb-ft.h>
 #endif
 
-#ifdef HAVE_OT
-#include <hb-ot.h>
-#endif
-
 #ifdef HAVE_UNISCRIBE
 #include <hb-uniscribe.h>
 #endif
@@ -58,7 +56,7 @@
 #endif
 
 int
-main (int argc, char **argv)
+main (void)
 {
   return !*hb_shape_list_shapers ();
 }
diff --git a/test/api/test-collect-unicodes.c b/test/api/test-collect-unicodes.c
new file mode 100644 (file)
index 0000000..50965a9
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+static void
+test_collect_unicodes_format4 (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.format4.ttf");
+  hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
+
+  hb_face_collect_unicodes (face, codepoints);
+
+  cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
+static void
+test_collect_unicodes_format12 (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.format12.ttf");
+  hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
+
+  hb_face_collect_unicodes (face, codepoints);
+
+  cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
+static void
+test_collect_unicodes (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_set_t *codepoints = hb_set_create();
+  hb_codepoint_t cp;
+
+  hb_face_collect_unicodes (face, codepoints);
+
+  cp = HB_SET_VALUE_INVALID;
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x61, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x62, ==, cp);
+  g_assert (hb_set_next (codepoints, &cp));
+  g_assert_cmpuint (0x63, ==, cp);
+  g_assert (!hb_set_next (codepoints, &cp));
+
+  hb_set_destroy (codepoints);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_collect_unicodes);
+  hb_test_add (test_collect_unicodes_format4);
+  hb_test_add (test_collect_unicodes_format12);
+
+  return hb_test_run();
+}
index f6f0d48..e9fae13 100644 (file)
@@ -32,7 +32,6 @@
 static void
 test_types_int (void)
 {
-  /* We already ASSERT_STATIC these in hb-private.h, but anyway */
   g_assert_cmpint (sizeof (int8_t), ==, 1);
   g_assert_cmpint (sizeof (uint8_t), ==, 1);
   g_assert_cmpint (sizeof (int16_t), ==, 2);
index 527dfcd..6690194 100644 (file)
@@ -83,7 +83,7 @@ free_up (void *user_data)
 }
 
 static hb_blob_t *
-get_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+get_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data HB_UNUSED)
 {
   if (tag == HB_TAG ('a','b','c','d'))
     return hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
@@ -210,10 +210,10 @@ test_fontfuncs_nil (void)
 }
 
 static hb_bool_t
-contour_point_func1 (hb_font_t *font, void *font_data,
-                    hb_codepoint_t glyph, unsigned int point_index,
+contour_point_func1 (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
+                    hb_codepoint_t glyph, unsigned int point_index HB_UNUSED,
                     hb_position_t *x, hb_position_t *y,
-                    void *user_data)
+                    void *user_data HB_UNUSED)
 {
   if (glyph == 1) {
     *x = 2;
@@ -230,10 +230,10 @@ contour_point_func1 (hb_font_t *font, void *font_data,
 }
 
 static hb_bool_t
-contour_point_func2 (hb_font_t *font, void *font_data,
+contour_point_func2 (hb_font_t *font, void *font_data HB_UNUSED,
                     hb_codepoint_t glyph, unsigned int point_index,
                     hb_position_t *x, hb_position_t *y,
-                    void *user_data)
+                    void *user_data HB_UNUSED)
 {
   if (glyph == 1) {
     *x = 6;
@@ -246,9 +246,9 @@ contour_point_func2 (hb_font_t *font, void *font_data,
 }
 
 static hb_position_t
-glyph_h_advance_func1 (hb_font_t *font, void *font_data,
+glyph_h_advance_func1 (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
                       hb_codepoint_t glyph,
-                      void *user_data)
+                      void *user_data HB_UNUSED)
 {
   if (glyph == 1)
     return 8;
@@ -361,8 +361,74 @@ test_fontfuncs_subclassing (void)
 
 
   hb_font_destroy (font3);
+  hb_font_destroy (font2);
+}
+
+static hb_bool_t
+nominal_glyph_func (hb_font_t *font HB_UNUSED,
+                   void *font_data HB_UNUSED,
+                   hb_codepoint_t unicode HB_UNUSED,
+                   hb_codepoint_t *glyph,
+                   void *user_data HB_UNUSED)
+{
+  *glyph = 0;
+  return FALSE;
+}
+
+static unsigned int
+nominal_glyphs_func (hb_font_t *font HB_UNUSED,
+                    void *font_data HB_UNUSED,
+                    unsigned int count HB_UNUSED,
+                    const hb_codepoint_t *first_unicode HB_UNUSED,
+                    unsigned int unicode_stride HB_UNUSED,
+                    hb_codepoint_t *first_glyph HB_UNUSED,
+                    unsigned int glyph_stride HB_UNUSED,
+                    void *user_data HB_UNUSED)
+{
+  return 0;
 }
 
+static void
+test_fontfuncs_parallels (void)
+{
+  hb_blob_t *blob;
+  hb_face_t *face;
+
+  hb_font_funcs_t *ffuncs1;
+  hb_font_funcs_t *ffuncs2;
+
+  hb_font_t *font0;
+  hb_font_t *font1;
+  hb_font_t *font2;
+  hb_codepoint_t glyph;
+
+  blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
+  face = hb_face_create (blob, 0);
+  hb_blob_destroy (blob);
+  font0 = hb_font_create (face);
+  hb_face_destroy (face);
+
+  /* setup sub-font1 */
+  font1 = hb_font_create_sub_font (font0);
+  hb_font_destroy (font0);
+  ffuncs1 = hb_font_funcs_create ();
+  hb_font_funcs_set_nominal_glyph_func (ffuncs1, nominal_glyph_func, NULL, NULL);
+  hb_font_set_funcs (font1, ffuncs1, NULL, NULL);
+  hb_font_funcs_destroy (ffuncs1);
+
+  /* setup sub-font2 */
+  font2 = hb_font_create_sub_font (font1);
+  hb_font_destroy (font1);
+  ffuncs2 = hb_font_funcs_create ();
+  hb_font_funcs_set_nominal_glyphs_func (ffuncs1, nominal_glyphs_func, NULL, NULL);
+  hb_font_set_funcs (font2, ffuncs2, NULL, NULL);
+  hb_font_funcs_destroy (ffuncs2);
+
+  /* Just test that calling get_nominal_glyph doesn't infinite-loop. */
+  hb_font_get_nominal_glyph (font2, 0x0020u, &glyph);
+
+  hb_font_destroy (font2);
+}
 
 static void
 test_font_empty (void)
@@ -470,6 +536,11 @@ test_font_properties (void)
   g_assert_cmpint (x_ppem, ==, 17);
   g_assert_cmpint (y_ppem, ==, 19);
 
+  /* Check ptem */
+  g_assert_cmpint (hb_font_get_ptem (font), ==, 0);
+  hb_font_set_ptem (font, 42);
+  g_assert_cmpint (hb_font_get_ptem (font), ==, 42);
+
 
   /* Check immutable */
 
@@ -542,6 +613,7 @@ main (int argc, char **argv)
   hb_test_add (test_fontfuncs_empty);
   hb_test_add (test_fontfuncs_nil);
   hb_test_add (test_fontfuncs_subclassing);
+  hb_test_add (test_fontfuncs_parallels);
 
   hb_test_add (test_font_empty);
   hb_test_add (test_font_properties);
diff --git a/test/api/test-map.c b/test/api/test-map.c
new file mode 100644 (file)
index 0000000..0911991
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ */
+
+#include "hb-test.h"
+
+/* Unit tests for hb-map.h */
+
+
+static void
+test_map_basic (void)
+{
+  hb_map_t *empty = hb_map_get_empty ();
+  hb_map_t *m;
+  g_assert (hb_map_is_empty (empty));
+  g_assert (!hb_map_allocation_successful (empty));
+  hb_map_destroy (empty);
+
+  m = hb_map_create ();
+  g_assert (hb_map_allocation_successful (m));
+  g_assert (hb_map_is_empty (m));
+
+  hb_map_set (m, 213, 223);
+  hb_map_set (m, 643, 675);
+  g_assert_cmpint (hb_map_get_population (m), ==, 2);
+
+  g_assert_cmpint (hb_map_get (m, 213), ==, 223);
+  g_assert (!hb_map_has (m, 123));
+  g_assert (hb_map_has (m, 213));
+
+  hb_map_del (m, 213);
+  g_assert (!hb_map_has (m, 213));
+
+  g_assert_cmpint (hb_map_get (m, 643), ==, 675);
+  hb_map_set (m, 237, 673);
+  g_assert (hb_map_has (m, 237));
+  hb_map_clear (m);
+  g_assert (!hb_map_has (m, 237));
+  g_assert (!hb_map_has (m, 643));
+  g_assert_cmpint (hb_map_get_population (m), ==, 0);
+
+  hb_map_destroy (m);
+}
+
+static void
+test_map_userdata (void)
+{
+  hb_map_t *m = hb_map_create ();
+
+  hb_user_data_key_t key[2];
+  int *data = (int *) malloc (sizeof (int));
+  int *data2;
+  *data = 3123;
+  hb_map_set_user_data (m, &key[0], data, free, TRUE);
+  g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 3123);
+
+  data2 = (int *) malloc (sizeof (int));
+  *data2 = 6343;
+  hb_map_set_user_data (m, &key[0], data2, free, FALSE);
+  g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 3123);
+  hb_map_set_user_data (m, &key[0], data2, free, TRUE);
+  g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 6343);
+
+  hb_map_destroy (m);
+}
+
+static void
+test_map_refcount (void)
+{
+  hb_map_t *m = hb_map_create ();
+  hb_map_t *m2;
+  hb_map_set (m, 213, 223);
+  g_assert_cmpint (hb_map_get (m, 213), ==, 223);
+
+  m2 = hb_map_reference (m);
+  hb_map_destroy (m);
+
+  /* We copied its reference so it is still usable after one destroy */
+  g_assert (hb_map_has (m, 213));
+  g_assert (hb_map_has (m2, 213));
+
+  hb_map_destroy (m2);
+
+  /* Now you can't access them anymore */
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_map_basic);
+  hb_test_add (test_map_userdata);
+  hb_test_add (test_map_refcount);
+
+  return hb_test_run();
+}
diff --git a/test/api/test-multithread.c b/test/api/test-multithread.c
new file mode 100644 (file)
index 0000000..f946049
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ *
+ */
+
+#include <pthread.h>
+
+#include <hb.h>
+#include <hb-ft.h>
+#include <hb-ot.h>
+
+#include "hb-test.h"
+
+static const char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
+static const char *text = "abc";
+
+static int num_threads = 30;
+static int num_iters = 200;
+
+static hb_font_t *font;
+static hb_buffer_t *ref_buffer;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void
+fill_the_buffer (hb_buffer_t *buffer)
+{
+  hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
+  hb_buffer_guess_segment_properties (buffer);
+  hb_shape (font, buffer, NULL, 0);
+}
+
+static void
+validity_check (hb_buffer_t *buffer) {
+  if (hb_buffer_diff (ref_buffer, buffer, (hb_codepoint_t) -1, 0))
+  {
+    fprintf (stderr, "One of the buffers was different from the reference.\n");
+    char out[255];
+
+    hb_buffer_serialize_glyphs (buffer, 0, hb_buffer_get_length (ref_buffer),
+                               out, sizeof (out), NULL,
+                               font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+                               HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
+    fprintf (stderr, "Actual:   %s\n", out);
+
+    hb_buffer_serialize_glyphs (ref_buffer, 0, hb_buffer_get_length (ref_buffer),
+                               out, sizeof (out), NULL,
+                               font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+                               HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
+    fprintf (stderr, "Expected: %s\n", out);
+
+    exit (1);
+  }
+}
+
+static void *
+thread_func (void *data)
+{
+  hb_buffer_t *buffer = (hb_buffer_t *) data;
+
+  pthread_mutex_lock (&mutex);
+  pthread_mutex_unlock (&mutex);
+
+  int i;
+  for (i = 0; i < num_iters; i++)
+  {
+    hb_buffer_clear_contents (buffer);
+    fill_the_buffer (buffer);
+    validity_check (buffer);
+  }
+
+  return 0;
+}
+
+static void
+test_body (void)
+{
+  int i;
+  pthread_t *threads = calloc (num_threads, sizeof (pthread_t));
+  hb_buffer_t **buffers = calloc (num_threads, sizeof (hb_buffer_t *));
+
+  pthread_mutex_lock (&mutex);
+
+  for (i = 0; i < num_threads; i++)
+  {
+    hb_buffer_t *buffer = hb_buffer_create ();
+    buffers[i] = buffer;
+    pthread_create (&threads[i], NULL, thread_func, buffer);
+  }
+
+  /* Let them loose! */
+  pthread_mutex_unlock (&mutex);
+
+  for (i = 0; i < num_threads; i++)
+  {
+    pthread_join (threads[i], NULL);
+    hb_buffer_destroy (buffers[i]);
+  }
+
+  free (buffers);
+  free (threads);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  char *path = argc > 1 && *argv[1] ? argv[1] : (char *) font_path;
+  if (argc > 2)
+    num_threads = atoi (argv[2]);
+  if (argc > 3)
+    num_iters = atoi (argv[3]);
+  if (argc > 4)
+    text = argv[4];
+
+  /* Dummy call to alleviate _guess_segment_properties thread safety-ness
+   * https://github.com/harfbuzz/harfbuzz/issues/1191 */
+  hb_language_get_default ();
+
+  hb_face_t *face = hb_test_open_font_file (path);
+  font = hb_font_create (face);
+
+  /* Fill the reference */
+  ref_buffer = hb_buffer_create ();
+  fill_the_buffer (ref_buffer);
+
+  /* Unnecessary, since version 2 it is ot-font by default */
+  hb_ot_font_set_funcs (font);
+  test_body ();
+
+  /* Test hb-ft in multithread */
+  hb_ft_font_set_funcs (font);
+  test_body ();
+
+  hb_buffer_destroy (ref_buffer);
+
+  hb_font_destroy (font);
+  hb_face_destroy (face);
+
+  return 0;
+}
index 02b9760..093615e 100644 (file)
@@ -235,7 +235,7 @@ test_object (void)
 
     {
       unsigned int j;
-      data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
+      data_t data[1000] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
       deadlock_test_t deadlock_test;
 
       g_test_message ("Testing object %s", o->name);
index 22584d2..c0cbd77 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2016  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -27,8 +28,6 @@
 #include "hb-test.h"
 
 #include <hb-ot.h>
-#include <stdlib.h>
-#include <stdio.h>
 
 /* Unit tests for hb-ot-color.h */
 
@@ -98,138 +97,142 @@ static hb_face_t *cpal_v0 = NULL;
 */
 static hb_face_t *cpal_v1 = NULL;
 
+static hb_face_t *cpal = NULL;
+static hb_face_t *cbdt = NULL;
+static hb_face_t *sbix = NULL;
+static hb_face_t *svg = NULL;
+static hb_face_t *empty = NULL;
 
 #define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START {        \
-  const hb_ot_color_t *_colors = (colors); \
+  const hb_color_t *_colors = (colors); \
   const size_t _i = (i); \
   const uint8_t red = (r), green = (g), blue = (b), alpha = (a); \
-  if (_colors[_i].red != red) { \
+  if (hb_color_get_red (_colors[_i]) != red) { \
     g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                               "colors[" #i "].red", _colors[_i].red, "==", red, 'x'); \
+                               "colors[" #i "]", _colors[_i], "==", red, 'x'); \
   } \
-  if (_colors[_i].green != green) { \
+  if (hb_color_get_green (_colors[_i]) != green) { \
     g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                               "colors[" #i "].green", _colors[_i].green, "==", green, 'x'); \
+                               "colors[" #i "]", _colors[_i], "==", green, 'x'); \
   } \
-  if (_colors[_i].blue != blue) { \
+  if (hb_color_get_blue (_colors[_i]) != blue) { \
     g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                               "colors[" #i "].blue", colors[i].blue, "==", blue, 'x'); \
+                               "colors[" #i "]", colors[_i], "==", blue, 'x'); \
   } \
-  if (_colors[_i].alpha != alpha) { \
+  if (hb_color_get_alpha (_colors[_i]) != alpha) { \
     g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                               "colors[" #i "].alpha", _colors[_i].alpha, "==", alpha, 'x'); \
+                               "colors[" #i "]", _colors[_i], "==", alpha, 'x'); \
   } \
 } G_STMT_END
 
 
-#if 0
 static void
-test_hb_ot_color_get_palette_count (void)
+test_hb_ot_color_palette_get_count (void)
 {
-  g_assert_cmpint (hb_ot_color_get_palette_count (hb_face_get_empty()), ==, 0);
-  g_assert_cmpint (hb_ot_color_get_palette_count (cpal_v0), ==, 2);
-  g_assert_cmpint (hb_ot_color_get_palette_count (cpal_v1), ==, 3);
+  g_assert_cmpint (hb_ot_color_palette_get_count (hb_face_get_empty()), ==, 0);
+  g_assert_cmpint (hb_ot_color_palette_get_count (cpal_v0), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_count (cpal_v1), ==, 3);
 }
 
 
 static void
-test_hb_ot_color_get_palette_name_id_empty (void)
+test_hb_ot_color_palette_get_name_id_empty (void)
 {
   /* numPalettes=0, so all calls are for out-of-bounds palette indices */
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 0), ==, 0xffff);
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 1), ==, 0xffff);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (hb_face_get_empty(), 0), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (hb_face_get_empty(), 1), ==, HB_OT_NAME_ID_INVALID);
 }
 
 
 static void
-test_hb_ot_color_get_palette_name_id_v0 (void)
+test_hb_ot_color_palette_get_name_id_v0 (void)
 {
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 0), ==, 0xffff);
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 1), ==, 0xffff);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 0), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 1), ==, HB_OT_NAME_ID_INVALID);
 
   /* numPalettes=2, so palette #2 is out of bounds */
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 2), ==, 0xffff);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 2), ==, HB_OT_NAME_ID_INVALID);
 }
 
 
 static void
-test_hb_ot_color_get_palette_name_id_v1 (void)
+test_hb_ot_color_palette_get_name_id_v1 (void)
 {
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 0), ==, 257);
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 1), ==, 0xffff);
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 2), ==, 258);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 0), ==, 257);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 1), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 2), ==, 258);
 
   /* numPalettes=3, so palette #3 is out of bounds */
-  g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 3), ==, 0xffff);
+  g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 3), ==, HB_OT_NAME_ID_INVALID);
 }
 
+
 static void
-test_hb_ot_color_get_palette_flags_empty (void)
+test_hb_ot_color_palette_get_flags_empty (void)
 {
   /* numPalettes=0, so all calls are for out-of-bounds palette indices */
-  g_assert_cmpint (hb_ot_color_get_palette_flags (hb_face_get_empty(), 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
-  g_assert_cmpint (hb_ot_color_get_palette_flags (hb_face_get_empty(), 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (hb_face_get_empty(), 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (hb_face_get_empty(), 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
 }
 
 
 static void
-test_hb_ot_color_get_palette_flags_v0 (void)
+test_hb_ot_color_palette_get_flags_v0 (void)
 {
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
 
   /* numPalettes=2, so palette #2 is out of bounds */
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
 }
 
 
 static void
-test_hb_ot_color_get_palette_flags_v1 (void)
+test_hb_ot_color_palette_get_flags_v1 (void)
 {
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND);
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND);
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
 
   /* numPalettes=3, so palette #3 is out of bounds */
-  g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
+  g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
 }
 
 
 static void
-test_hb_ot_color_get_palette_colors_empty (void)
+test_hb_ot_color_palette_get_colors_empty (void)
 {
-  hb_face_t *empty = hb_face_get_empty ();
-  g_assert_cmpint (hb_ot_color_get_palette_colors (empty, 0, 0, NULL, NULL), ==, 0);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (empty, 0, 0, NULL, NULL), ==, 0);
 }
 
 
 static void
-test_hb_ot_color_get_palette_colors_v0 (void)
+test_hb_ot_color_palette_get_colors_v0 (void)
 {
-  unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v0, 0, 0, NULL, NULL);
-  hb_ot_color_t *colors = (hb_ot_color_t*) alloca (num_colors * sizeof (hb_ot_color_t));
+  unsigned int num_colors = hb_ot_color_palette_get_colors (cpal_v0, 0, 0, NULL, NULL);
+  hb_color_t *colors = (hb_color_t*) alloca (num_colors * sizeof (hb_color_t));
   size_t colors_size = num_colors * sizeof(*colors);
   g_assert_cmpint (num_colors, ==, 2);
 
   /* Palette #0, start_index=0 */
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 2);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0x66, 0xcc, 0xff, 0xff);
 
   /* Palette #1, start_index=0 */
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 1, 0, &num_colors, colors), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 1, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 2);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0x80, 0x00, 0x00, 0xff);
 
   /* Palette #2 (there are only #0 and #1 in the font, so this is out of bounds) */
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 2, 0, &num_colors, colors), ==, 0);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 2, 0, &num_colors, colors), ==, 0);
 
   /* Palette #0, start_index=1 */
   memset(colors, 0x33, colors_size);
   num_colors = 2;
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 1, &num_colors, colors), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 1, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 1);
   assert_color_rgba (colors, 0, 0x66, 0xcc, 0xff, 0xff);
   assert_color_rgba (colors, 1, 0x33, 0x33, 0x33, 0x33);  /* untouched */
@@ -237,15 +240,15 @@ test_hb_ot_color_get_palette_colors_v0 (void)
   /* Palette #0, start_index=0, pretend that we have only allocated space for 1 color */
   memset(colors, 0x44, colors_size);
   num_colors = 1;
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 1);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44);  /* untouched */
 
   /* start_index > numPaletteEntries */
-  memset(colors, 0x44, colors_size);
+  memset (colors, 0x44, colors_size);
   num_colors = 2;
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 9876, &num_colors, colors), ==, 2);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 9876, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 0);
   assert_color_rgba (colors, 0, 0x44, 0x44, 0x44, 0x44);  /* untouched */
   assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44);  /* untouched */
@@ -253,46 +256,199 @@ test_hb_ot_color_get_palette_colors_v0 (void)
 
 
 static void
-test_hb_ot_color_get_palette_colors_v1 (void)
+test_hb_ot_color_palette_get_colors_v1 (void)
 {
-  hb_ot_color_t colors[3];
-  unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v1, 0, 0, NULL, NULL);
-  size_t colors_size = 3 * sizeof(*colors);
+  hb_color_t colors[3];
+  unsigned int num_colors = hb_ot_color_palette_get_colors (cpal_v1, 0, 0, NULL, NULL);
+  size_t colors_size = 3 * sizeof (hb_color_t);
   g_assert_cmpint (num_colors, ==, 2);
 
   /* Palette #0, start_index=0 */
-  memset(colors, 0x77, colors_size);
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 0, 0, &num_colors, colors), ==, 2);
+  memset (colors, 0x77, colors_size);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 0, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 2);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0x66, 0xcc, 0xff, 0xff);
   assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77);  /* untouched */
 
   /* Palette #1, start_index=0 */
-  memset(colors, 0x77, colors_size);
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 1, 0, &num_colors, colors), ==, 2);
+  memset (colors, 0x77, colors_size);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 1, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 2);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0xff, 0xcc, 0x66, 0xff);
   assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77);  /* untouched */
 
   /* Palette #2, start_index=0 */
-  memset(colors, 0x77, colors_size);
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 2, 0, &num_colors, colors), ==, 2);
+  memset (colors, 0x77, colors_size);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 2, 0, &num_colors, colors), ==, 2);
   g_assert_cmpint (num_colors, ==, 2);
   assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 1, 0x80, 0x00, 0x00, 0xff);
   assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77);  /* untouched */
 
   /* Palette #3 (out of bounds), start_index=0 */
-  memset(colors, 0x77, colors_size);
-  g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 3, 0, &num_colors, colors), ==, 0);
+  memset (colors, 0x77, colors_size);
+  g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 3, 0, &num_colors, colors), ==, 0);
   g_assert_cmpint (num_colors, ==, 0);
   assert_color_rgba (colors, 0, 0x77, 0x77, 0x77, 0x77);  /* untouched */
   assert_color_rgba (colors, 1, 0x77, 0x77, 0x77, 0x77);  /* untouched */
   assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77);  /* untouched */
 }
-#endif
+
+
+static void
+test_hb_ot_color_palette_color_get_name_id (void)
+{
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 0), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 1), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 2), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 0), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 1), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 2), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 0), ==, HB_OT_NAME_ID_INVALID);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 1), ==, 256);
+  g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 2), ==, HB_OT_NAME_ID_INVALID);
+}
+
+
+static void
+test_hb_ot_color_glyph_get_layers (void)
+{
+  hb_ot_color_layer_t layers[1];
+  unsigned int count = 1;
+  unsigned int num_layers;
+
+  g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 0, 0,
+                                                 NULL, NULL), ==, 0);
+  g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 1, 0,
+                                                 NULL, NULL), ==, 0);
+  g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 2, 0,
+                                                 NULL, NULL), ==, 2);
+
+  num_layers = hb_ot_color_glyph_get_layers (cpal_v1, 2, 0, &count, layers);
+
+  g_assert_cmpuint (num_layers, ==, 2);
+  g_assert_cmpuint (count, ==, 1);
+  g_assert_cmpuint (layers[0].glyph, ==, 3);
+  g_assert_cmpuint (layers[0].color_index, ==, 1);
+
+  count = 1;
+  hb_ot_color_glyph_get_layers (cpal_v1, 2, 1, &count, layers);
+
+  g_assert_cmpuint (num_layers, ==, 2);
+  g_assert_cmpuint (count, ==, 1);
+  g_assert_cmpuint (layers[0].glyph, ==, 4);
+  g_assert_cmpuint (layers[0].color_index, ==, 0);
+}
+
+static void
+test_hb_ot_color_has_data (void)
+{
+  g_assert (hb_ot_color_has_layers (empty) == FALSE);
+  g_assert (hb_ot_color_has_layers (cpal_v0) == TRUE);
+  g_assert (hb_ot_color_has_layers (cpal_v1) == TRUE);
+  g_assert (hb_ot_color_has_layers (cpal) == TRUE);
+  g_assert (hb_ot_color_has_layers (cbdt) == FALSE);
+  g_assert (hb_ot_color_has_layers (sbix) == FALSE);
+  g_assert (hb_ot_color_has_layers (svg) == FALSE);
+
+  g_assert (hb_ot_color_has_palettes (empty) == FALSE);
+  g_assert (hb_ot_color_has_palettes (cpal_v0) == TRUE);
+  g_assert (hb_ot_color_has_palettes (cpal_v1) == TRUE);
+  g_assert (hb_ot_color_has_palettes (cpal) == TRUE);
+  g_assert (hb_ot_color_has_palettes (cbdt) == FALSE);
+  g_assert (hb_ot_color_has_palettes (sbix) == FALSE);
+  g_assert (hb_ot_color_has_palettes (svg) == FALSE);
+
+  g_assert (hb_ot_color_has_svg (empty) == FALSE);
+  g_assert (hb_ot_color_has_svg (cpal_v0) == FALSE);
+  g_assert (hb_ot_color_has_svg (cpal_v1) == FALSE);
+  g_assert (hb_ot_color_has_svg (cpal) == FALSE);
+  g_assert (hb_ot_color_has_svg (cbdt) == FALSE);
+  g_assert (hb_ot_color_has_svg (sbix) == FALSE);
+  g_assert (hb_ot_color_has_svg (svg) == TRUE);
+
+  g_assert (hb_ot_color_has_png (empty) == FALSE);
+  g_assert (hb_ot_color_has_png (cpal_v0) == FALSE);
+  g_assert (hb_ot_color_has_png (cpal_v1) == FALSE);
+  g_assert (hb_ot_color_has_png (cpal) == FALSE);
+  g_assert (hb_ot_color_has_png (cbdt) == TRUE);
+  g_assert (hb_ot_color_has_png (sbix) == TRUE);
+  g_assert (hb_ot_color_has_png (svg) == FALSE);
+}
+
+static void
+test_hb_ot_color_svg (void)
+{
+  hb_blob_t *blob;
+  unsigned int length;
+  const char *data;
+
+  blob = hb_ot_color_glyph_reference_svg (svg, 0);
+  g_assert (hb_blob_get_length (blob) == 0);
+
+  blob = hb_ot_color_glyph_reference_svg (svg, 1);
+  data = hb_blob_get_data (blob, &length);
+  g_assert_cmpuint (length, ==, 146);
+  g_assert (strncmp (data, "<?xml", 4) == 0);
+  g_assert (strncmp (data + 140, "</svg>", 5) == 0);
+  hb_blob_destroy (blob);
+
+  blob = hb_ot_color_glyph_reference_svg (empty, 0);
+  g_assert (hb_blob_get_length (blob) == 0);
+}
+
+
+static void
+test_hb_ot_color_png (void)
+{
+  hb_blob_t *blob;
+  unsigned int length;
+  const char *data;
+  hb_glyph_extents_t extents;
+  hb_font_t *cbdt_font;
+
+  /* sbix */
+  hb_font_t *sbix_font;
+  sbix_font = hb_font_create (sbix);
+  blob = hb_ot_color_glyph_reference_png (sbix_font, 0);
+  hb_font_get_glyph_extents (sbix_font, 0, &extents);
+  g_assert_cmpint (extents.x_bearing, ==, 0);
+  g_assert_cmpint (extents.y_bearing, ==, 0);
+  g_assert_cmpint (extents.width, ==, 0);
+  g_assert_cmpint (extents.height, ==, 0);
+  g_assert (hb_blob_get_length (blob) == 0);
+
+  blob = hb_ot_color_glyph_reference_png (sbix_font, 1);
+  data = hb_blob_get_data (blob, &length);
+  g_assert_cmpuint (length, ==, 224);
+  g_assert (strncmp (data + 1, "PNG", 3) == 0);
+  hb_font_get_glyph_extents (sbix_font, 1, &extents);
+  g_assert_cmpint (extents.x_bearing, ==, 0);
+  g_assert_cmpint (extents.y_bearing, ==, 0);
+  g_assert_cmpint (extents.width, ==, 800);
+  g_assert_cmpint (extents.height, ==, 800);
+  hb_blob_destroy (blob);
+  hb_font_destroy (sbix_font);
+
+  /* cbdt */
+  cbdt_font = hb_font_create (cbdt);
+  blob = hb_ot_color_glyph_reference_png (cbdt_font, 0);
+  g_assert (hb_blob_get_length (blob) == 0);
+
+  blob = hb_ot_color_glyph_reference_png (cbdt_font, 1);
+  data = hb_blob_get_data (blob, &length);
+  g_assert_cmpuint (length, ==, 88);
+  g_assert (strncmp (data + 1, "PNG", 3) == 0);
+  hb_font_get_glyph_extents (cbdt_font, 1, &extents);
+  g_assert_cmpint (extents.x_bearing, ==, 0);
+  g_assert_cmpint (extents.y_bearing, ==, 1024);
+  g_assert_cmpint (extents.width, ==, 1024);
+  g_assert_cmpint (extents.height, ==, -1024);
+  hb_blob_destroy (blob);
+  hb_font_destroy (cbdt_font);
+}
 
 int
 main (int argc, char **argv)
@@ -300,20 +456,34 @@ main (int argc, char **argv)
   int status = 0;
 
   hb_test_init (&argc, &argv);
-  // cpal_v0 = hb_test_load_face ("../shaping/data/in-house/fonts/e90374e5e439e00725b4fe7a8d73db57c5a97f82.ttf");
-  // cpal_v1 = hb_test_load_face ("../shaping/data/in-house/fonts/319f5d7ebffbefc5c5e6569f8cea73444d7a7268.ttf");
-  // hb_test_add (test_hb_ot_color_get_palette_count);
-  // hb_test_add (test_hb_ot_color_get_palette_name_id_empty);
-  // hb_test_add (test_hb_ot_color_get_palette_name_id_v0);
-  // hb_test_add (test_hb_ot_color_get_palette_name_id_v1);
-  // hb_test_add (test_hb_ot_color_get_palette_flags_empty);
-  // hb_test_add (test_hb_ot_color_get_palette_flags_v0);
-  // hb_test_add (test_hb_ot_color_get_palette_flags_v1);
-  // hb_test_add (test_hb_ot_color_get_palette_colors_empty);
-  // hb_test_add (test_hb_ot_color_get_palette_colors_v0);
-  // hb_test_add (test_hb_ot_color_get_palette_colors_v1);
+  cpal_v0 = hb_test_open_font_file ("fonts/cpal-v0.ttf");
+  cpal_v1 = hb_test_open_font_file ("fonts/cpal-v1.ttf");
+  cpal = hb_test_open_font_file ("fonts/chromacheck-colr.ttf");
+  cbdt = hb_test_open_font_file ("fonts/chromacheck-cbdt.ttf");
+  sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf");
+  svg = hb_test_open_font_file ("fonts/chromacheck-svg.ttf");
+  empty = hb_face_get_empty ();
+  hb_test_add (test_hb_ot_color_palette_get_count);
+  hb_test_add (test_hb_ot_color_palette_get_name_id_empty);
+  hb_test_add (test_hb_ot_color_palette_get_name_id_v0);
+  hb_test_add (test_hb_ot_color_palette_get_name_id_v1);
+  hb_test_add (test_hb_ot_color_palette_get_flags_empty);
+  hb_test_add (test_hb_ot_color_palette_get_flags_v0);
+  hb_test_add (test_hb_ot_color_palette_get_flags_v1);
+  hb_test_add (test_hb_ot_color_palette_get_colors_empty);
+  hb_test_add (test_hb_ot_color_palette_get_colors_v0);
+  hb_test_add (test_hb_ot_color_palette_get_colors_v1);
+  hb_test_add (test_hb_ot_color_palette_color_get_name_id);
+  hb_test_add (test_hb_ot_color_glyph_get_layers);
+  hb_test_add (test_hb_ot_color_has_data);
+  hb_test_add (test_hb_ot_color_png);
+  hb_test_add (test_hb_ot_color_svg);
   status = hb_test_run();
   hb_face_destroy (cpal_v0);
   hb_face_destroy (cpal_v1);
+  hb_face_destroy (cpal);
+  hb_face_destroy (cbdt);
+  hb_face_destroy (sbix);
+  hb_face_destroy (svg);
   return status;
 }
diff --git a/test/api/test-ot-extents-cff.c b/test/api/test-ot-extents-cff.c
new file mode 100644 (file)
index 0000000..49b8799
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include <hb-ot.h>
+
+/* Unit tests for CFF/CFF2 glyph extents */
+
+static void
+test_extents_cff1 (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
+  g_assert (face);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+  g_assert (font);
+  hb_ot_font_set_funcs (font);
+
+  hb_glyph_extents_t  extents;
+  hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 52);
+  g_assert_cmpint (extents.y_bearing, ==, 498);
+  g_assert_cmpint (extents.width, ==, 381);
+  g_assert_cmpint (extents.height, ==, -510);
+
+  hb_font_destroy (font);
+
+  hb_face_t *face_j = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
+  g_assert (face_j);
+  hb_font_t *font_j = hb_font_create (face_j);
+  hb_face_destroy (face_j);
+  g_assert (font_j);
+  hb_ot_font_set_funcs (font_j);
+
+  hb_bool_t result_j = hb_font_get_glyph_extents (font_j, 3, &extents);
+  g_assert (result_j);
+
+  g_assert_cmpint (extents.x_bearing, ==, 34);
+  g_assert_cmpint (extents.y_bearing, ==, 840);
+  g_assert_cmpint (extents.width, ==, 920);
+  g_assert_cmpint (extents.height, ==, -907);
+
+  hb_font_destroy (font_j);
+}
+
+static void
+test_extents_cff1_flex (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_flex.otf");
+  g_assert (face);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+  g_assert (font);
+  hb_ot_font_set_funcs (font);
+
+  hb_glyph_extents_t  extents;
+  hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, -20);
+  g_assert_cmpint (extents.y_bearing, ==, 520);
+  g_assert_cmpint (extents.width, ==, 540);
+  g_assert_cmpint (extents.height, ==, -540);
+
+  hb_font_destroy (font);
+}
+
+static void
+test_extents_cff1_seac (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
+  g_assert (face);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+  g_assert (font);
+  hb_ot_font_set_funcs (font);
+
+  hb_glyph_extents_t  extents;
+  hb_bool_t result = hb_font_get_glyph_extents (font, 3, &extents); /* Agrave */
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 3);
+  g_assert_cmpint (extents.y_bearing, ==, 861);
+  g_assert_cmpint (extents.width, ==, 538);
+  g_assert_cmpint (extents.height, ==, -861);
+
+  result = hb_font_get_glyph_extents (font, 4, &extents); /* Udieresis */
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 87);
+  g_assert_cmpint (extents.y_bearing, ==, 827);
+  g_assert_cmpint (extents.width, ==, 471);
+  g_assert_cmpint (extents.height, ==, -839);
+
+  hb_font_destroy (font);
+}
+
+static void
+test_extents_cff2 (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  g_assert (face);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+  g_assert (font);
+  hb_ot_font_set_funcs (font);
+
+  hb_glyph_extents_t  extents;
+  hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 46);
+  g_assert_cmpint (extents.y_bearing, ==, 487);
+  g_assert_cmpint (extents.width, ==, 455);
+  g_assert_cmpint (extents.height, ==, -500);
+
+  float coords[2] = { 600.0f, 50.0f };
+  hb_font_set_var_coords_design (font, coords, 2);
+  result = hb_font_get_glyph_extents (font, 1, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 38);
+  g_assert_cmpint (extents.y_bearing, ==, 493);
+  g_assert_cmpint (extents.width, ==, 481);
+  g_assert_cmpint (extents.height, ==, -508);
+
+  hb_font_destroy (font);
+}
+
+static void
+test_extents_cff2_vsindex (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/AdobeVFPrototype_vsindex.otf");
+  g_assert (face);
+  hb_font_t *font = hb_font_create (face);
+  hb_face_destroy (face);
+  g_assert (font);
+  hb_ot_font_set_funcs (font);
+
+  hb_glyph_extents_t  extents;
+  float coords[2] = { 800.0f, 50.0f };
+  hb_font_set_var_coords_design (font, coords, 2);
+  hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 11);
+  g_assert_cmpint (extents.y_bearing, ==, 656);
+  g_assert_cmpint (extents.width, ==, 653);
+  g_assert_cmpint (extents.height, ==, -656);
+
+  result = hb_font_get_glyph_extents (font, 2, &extents);
+  g_assert (result);
+
+  g_assert_cmpint (extents.x_bearing, ==, 7);
+  g_assert_cmpint (extents.y_bearing, ==, 669);
+  g_assert_cmpint (extents.width, ==, 650);
+  g_assert_cmpint (extents.height, ==, -669);
+
+  hb_font_destroy (font);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_extents_cff1);
+  hb_test_add (test_extents_cff1_flex);
+  hb_test_add (test_extents_cff1_seac);
+  hb_test_add (test_extents_cff2);
+  hb_test_add (test_extents_cff2_vsindex);
+
+  return hb_test_run ();
+}
diff --git a/test/api/test-ot-face.c b/test/api/test-ot-face.c
new file mode 100644 (file)
index 0000000..f2d2fca
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2011  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef TEST_OT_FACE_NO_MAIN
+#include "hb-test.h"
+#endif
+#include <hb-ot.h>
+
+/* Unit tests for hb-ot-*.h */
+
+
+static void
+test_face (hb_face_t *face,
+          hb_codepoint_t cp)
+{
+  hb_font_t *font = hb_font_create (face);
+  hb_set_t *set;
+  hb_codepoint_t g;
+  hb_position_t x, y;
+  char buf[5] = {0};
+  unsigned int len;
+  hb_glyph_extents_t extents;
+  hb_ot_font_set_funcs (font);
+
+  set = hb_set_create ();
+  hb_face_collect_unicodes (face, set);
+  hb_face_collect_variation_selectors (face, set);
+  hb_face_collect_variation_unicodes (face, cp, set);
+
+  hb_font_get_nominal_glyph (font, cp, &g);
+  hb_font_get_variation_glyph (font, cp, cp, &g);
+  hb_font_get_glyph_h_advance (font, cp);
+  hb_font_get_glyph_v_advance (font, cp);
+  hb_font_get_glyph_h_origin (font, cp, &x, &y);
+  hb_font_get_glyph_v_origin (font, cp, &x, &y);
+  hb_font_get_glyph_extents (font, cp, &extents);
+  hb_font_get_glyph_contour_point (font, cp, 0, &x, &y);
+  hb_font_get_glyph_name (font, cp, buf, sizeof (buf));
+  hb_font_get_glyph_from_name (font, buf, strlen (buf), &g);
+
+  hb_ot_color_has_palettes (face);
+  hb_ot_color_palette_get_count (face);
+  hb_ot_color_palette_get_name_id (face, cp);
+  hb_ot_color_palette_color_get_name_id (face, cp);
+  hb_ot_color_palette_get_flags (face, cp);
+  hb_ot_color_palette_get_colors (face, cp, 0, NULL, NULL);
+  hb_ot_color_has_layers (face);
+  hb_ot_color_glyph_get_layers (face, cp, 0, NULL, NULL);
+  hb_ot_color_has_svg (face);
+  hb_blob_destroy (hb_ot_color_glyph_reference_svg (face, cp));
+  hb_ot_color_has_png (face);
+  hb_blob_destroy (hb_ot_color_glyph_reference_png (font, cp));
+
+  hb_ot_layout_has_glyph_classes (face);
+  hb_ot_layout_has_substitution (face);
+  hb_ot_layout_has_positioning (face);
+
+  hb_ot_math_has_data (face);
+  hb_ot_math_get_constant (font, HB_OT_MATH_CONSTANT_MATH_LEADING);
+  hb_ot_math_get_glyph_italics_correction (font, cp);
+  hb_ot_math_get_glyph_top_accent_attachment (font, cp);
+  hb_ot_math_is_glyph_extended_shape (face, cp);
+  hb_ot_math_get_glyph_kerning (font, cp, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0);
+  hb_ot_math_get_glyph_variants (font, cp, HB_DIRECTION_TTB, 0, NULL, NULL);
+  hb_ot_math_get_min_connector_overlap (font, HB_DIRECTION_RTL);
+  hb_ot_math_get_glyph_assembly (font, cp, HB_DIRECTION_BTT, 0, NULL, NULL, NULL);
+
+  len = sizeof (buf);
+  hb_ot_name_list_names (face, NULL);
+  hb_ot_name_get_utf8 (face, cp, NULL, &len, buf);
+  hb_ot_name_get_utf16 (face, cp, NULL, NULL, NULL);
+  hb_ot_name_get_utf32 (face, cp, NULL, NULL, NULL);
+
+  hb_ot_var_get_axis_count (face);
+  hb_ot_var_get_axis_infos (face, 0, NULL, NULL);
+  hb_ot_var_normalize_variations (face, NULL, 0, NULL, 0);
+  hb_ot_var_normalize_coords (face, 0, NULL, NULL);
+
+  hb_set_destroy (set);
+  hb_font_destroy (font);
+}
+
+#ifndef TEST_OT_FACE_NO_MAIN
+static void
+test_ot_face_empty (void)
+{
+  test_face (hb_face_get_empty (), 0);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_ot_face_empty);
+
+  return hb_test_run();
+}
+#endif
diff --git a/test/api/test-ot-ligature-carets.c b/test/api/test-ot-ligature-carets.c
new file mode 100644 (file)
index 0000000..d842785
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ *
+ */
+
+#include "hb-test.h"
+
+#include <hb-ot.h>
+
+static void
+test_ot_layout_feature_get_name_ids_and_characters (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/lcar.ttf");
+  hb_font_t *font = hb_font_create (face);
+  hb_font_set_scale (font, hb_face_get_upem (face) * 2, hb_face_get_upem (face) * 4);
+
+  hb_position_t caret_array[2];
+  unsigned int caret_count = 2;
+  g_assert_cmpuint (2, ==, hb_ot_layout_get_ligature_carets (font, HB_DIRECTION_RTL,
+                                                            98, 0, &caret_count,
+                                                            caret_array));
+
+  g_assert_cmpuint (2, ==, caret_count);
+  g_assert_cmpuint (1130, ==, caret_array[0]);
+  g_assert_cmpuint (2344, ==, caret_array[1]);
+
+  g_assert_cmpuint (2, ==, hb_ot_layout_get_ligature_carets (font, HB_DIRECTION_BTT,
+                                                            98, 0, &caret_count,
+                                                            caret_array));
+
+  g_assert_cmpuint (2, ==, caret_count);
+  g_assert_cmpuint (2260, ==, caret_array[0]);
+  g_assert_cmpuint (4688, ==, caret_array[1]);
+
+  hb_font_destroy (font);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  hb_test_add (test_ot_layout_feature_get_name_ids_and_characters);
+
+  return hb_test_run ();
+}
index 0ca5566..7f50015 100644 (file)
@@ -100,10 +100,14 @@ test_has_data (void)
   hb_face = hb_face_get_empty ();
   hb_font = hb_font_create (hb_face);
   g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
+  hb_font_destroy (hb_font);
+  hb_face_destroy (hb_face);
 
   hb_font = hb_font_get_empty ();
   hb_face = hb_font_get_face (hb_font);
   g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available
+  hb_font_destroy (hb_font);
+  hb_face_destroy (hb_face);
 
   cleanupFreeType();
 }
@@ -396,8 +400,8 @@ test_get_min_connector_overlap (void)
   initFreeType();
 
   openFont("fonts/MathTestFontEmpty.otf");
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available
-  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 0); // MathVariants not available
+  g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 0); // MathVariants not available
   closeFont();
 
   openFont("fonts/MathTestFontPartial1.otf");
diff --git a/test/api/test-ot-name.c b/test/api/test-ot-name.c
new file mode 100644 (file)
index 0000000..c2ae4fd
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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.
+ *
+ */
+
+#include "hb-test.h"
+
+#include <hb-ot.h>
+
+static hb_face_t *face;
+
+static void
+test_ot_layout_feature_get_name_ids_and_characters (void)
+{
+  hb_tag_t cv01 = HB_TAG ('c','v','0','1');
+  unsigned int feature_index;
+  unsigned int num_named_parameters;
+  hb_ot_name_id_t label_id;
+  hb_ot_name_id_t tooltip_id;
+  hb_ot_name_id_t sample_id;
+  hb_ot_name_id_t first_param_id;
+  hb_codepoint_t characters[100];
+  unsigned int char_count = 100;
+  unsigned int all_chars;
+  if (!hb_ot_layout_language_find_feature (face,
+                                          HB_OT_TAG_GSUB,
+                                          0,
+                                          HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
+                                          cv01,
+                                          &feature_index))
+     g_error ("Failed to find feature index");
+
+  if (!hb_ot_layout_feature_get_name_ids (face, HB_OT_TAG_GSUB, feature_index,
+                                         &label_id, &tooltip_id, &sample_id,
+                                         &num_named_parameters, &first_param_id))
+    g_error ("Failed to get name ids");
+
+  g_assert_cmpint (label_id, ==, 256);
+  g_assert_cmpint (tooltip_id, ==, 257);
+  g_assert_cmpint (sample_id, ==, 258);
+  g_assert_cmpint (num_named_parameters, ==, 2);
+  g_assert_cmpint (first_param_id, ==, 259);
+
+  all_chars = hb_ot_layout_feature_get_characters (face, HB_OT_TAG_GSUB, feature_index,
+                                                  0, &char_count, characters);
+
+  g_assert_cmpint (all_chars, ==, 2);
+  g_assert_cmpint (char_count, ==, 2);
+  g_assert_cmpint (characters[0], ==, 10);
+  g_assert_cmpint (characters[1], ==, 24030);
+}
+
+static void
+test_ot_name (void)
+{
+  unsigned int num_entries;
+  const hb_ot_name_entry_t *entries;
+  hb_ot_name_id_t name_id;
+  hb_language_t lang;
+  char text[10];
+  unsigned int text_size = 10;
+  entries = hb_ot_name_list_names (face, &num_entries);
+  g_assert_cmpuint (12, ==, num_entries);
+  name_id = entries[3].name_id;
+  g_assert_cmpuint (3, ==, name_id);
+  lang = entries[3].language;
+  g_assert_cmpstr (hb_language_to_string (lang), ==, "en");
+  g_assert_cmpuint (27, ==, hb_ot_name_get_utf8 (face, name_id, lang, &text_size, text));
+  g_assert_cmpuint (9, ==, text_size);
+  g_assert_cmpstr (text, ==, "FontForge");
+}
+
+int
+main (int argc, char **argv)
+{
+  unsigned int status;
+  g_test_init (&argc, &argv, NULL);
+
+  hb_test_add (test_ot_layout_feature_get_name_ids_and_characters);
+  hb_test_add (test_ot_name);
+
+  face = hb_test_open_font_file ("fonts/cv01.otf");
+  status = hb_test_run ();
+  hb_face_destroy (face);
+  return status;
+}
index e821b36..60231af 100644 (file)
@@ -37,50 +37,86 @@ static void
 test_simple_tags (const char *s, hb_script_t script)
 {
   hb_script_t tag;
-  hb_tag_t t1, t2;
+  unsigned int count = 2;
+  hb_tag_t t[2];
 
   g_test_message ("Testing script %c%c%c%c: tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s);
   tag = hb_tag_from_string (s, -1);
 
-  hb_ot_tags_from_script (script, &t1, &t2);
+  hb_ot_tags_from_script_and_language (script,
+                                      HB_LANGUAGE_INVALID,
+                                      &count, t, NULL, NULL);
 
-  g_assert_cmphex (t1, ==, tag);
-  g_assert_cmphex (t2, ==, HB_OT_TAG_DEFAULT_SCRIPT);
+  if (count)
+    g_assert_cmphex (t[0], ==, tag);
+  else
+    g_assert_cmphex (HB_TAG_CHAR4 ("DFLT"), ==, tag);
 
   g_assert_cmphex (hb_ot_tag_to_script (tag), ==, script);
 }
 
 static void
-test_indic_tags (const char *s1, const char *s2, hb_script_t script)
+test_script_tags_from_language (const char *s, const char *lang_s, hb_script_t script)
 {
-  hb_script_t tag1, tag2;
-  hb_script_t t1, t2;
+  hb_script_t tag;
+  unsigned int count = 1;
+  hb_tag_t t;
+
+  g_test_message ("Testing script %c%c%c%c: script tag %s, language tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s, lang_s);
+  tag = hb_tag_from_string (s, -1);
+
+  hb_ot_tags_from_script_and_language (script, hb_language_from_string (lang_s, -1), &count, &t, NULL, NULL);
+
+  if (count != 0)
+  {
+    g_assert_cmpuint (count, ==, 1);
+    g_assert_cmphex (t, ==, tag);
+  }
+}
 
-  g_test_message ("Testing script %c%c%c%c: new tag %s, old tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s1, s2);
+static void
+test_indic_tags (const char *s1, const char *s2, const char *s3, hb_script_t script)
+{
+  hb_script_t tag1, tag2, tag3;
+  hb_tag_t t[3];
+  unsigned int count = 3;
+
+  g_test_message ("Testing script %c%c%c%c: USE tag %s, new tag %s, old tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s1, s2, s3);
   tag1 = hb_tag_from_string (s1, -1);
   tag2 = hb_tag_from_string (s2, -1);
+  tag3 = hb_tag_from_string (s3, -1);
 
-  hb_ot_tags_from_script (script, &t1, &t2);
+  hb_ot_tags_from_script_and_language (script,
+                                      HB_LANGUAGE_INVALID,
+                                      &count, t, NULL, NULL);
 
-  g_assert_cmphex (t1, ==, tag1);
-  g_assert_cmphex (t2, ==, tag2);
+  g_assert_cmpuint (count, ==, 3);
+  g_assert_cmphex (t[0], ==, tag1);
+  g_assert_cmphex (t[1], ==, tag2);
+  g_assert_cmphex (t[2], ==, tag3);
 
   g_assert_cmphex (hb_ot_tag_to_script (tag1), ==, script);
   g_assert_cmphex (hb_ot_tag_to_script (tag2), ==, script);
+  g_assert_cmphex (hb_ot_tag_to_script (tag3), ==, script);
 }
 
 static void
 test_ot_tag_script_degenerate (void)
 {
-  hb_tag_t t1, t2;
+  hb_tag_t t[2];
+  unsigned int count = 2;
 
   g_assert_cmphex (HB_TAG_CHAR4 ("DFLT"), ==, HB_OT_TAG_DEFAULT_SCRIPT);
 
   /* HIRAGANA and KATAKANA both map to 'kana' */
   test_simple_tags ("kana", HB_SCRIPT_KATAKANA);
-  hb_ot_tags_from_script (HB_SCRIPT_HIRAGANA, &t1, &t2);
-  g_assert_cmphex (t1, ==, HB_TAG_CHAR4 ("kana"));
-  g_assert_cmphex (t2, ==, HB_OT_TAG_DEFAULT_SCRIPT);
+
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_HIRAGANA,
+                                      HB_LANGUAGE_INVALID,
+                                      &count, t, NULL, NULL);
+
+  g_assert_cmpuint (count, ==, 1);
+  g_assert_cmphex (t[0], ==, HB_TAG_CHAR4 ("kana"));
 
   test_simple_tags ("DFLT", HB_SCRIPT_INVALID);
 
@@ -121,18 +157,40 @@ test_ot_tag_script_simple (void)
 }
 
 static void
+test_ot_tag_script_from_language (void)
+{
+  test_script_tags_from_language (NULL, NULL, HB_SCRIPT_INVALID);
+  test_script_tags_from_language (NULL, "en", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("copt", "en", HB_SCRIPT_COPTIC);
+  test_script_tags_from_language (NULL, "x-hbsc", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("copt", "x-hbsc", HB_SCRIPT_COPTIC);
+  test_script_tags_from_language ("abc ", "x-hbscabc", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("deva", "x-hbscdeva", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("dev2", "x-hbscdev2", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("dev3", "x-hbscdev3", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("copt", "x-hbotpap0-hbsccopt", HB_SCRIPT_INVALID);
+  test_script_tags_from_language (NULL, "en-x-hbsc", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("copt", "en-x-hbsc", HB_SCRIPT_COPTIC);
+  test_script_tags_from_language ("abc ", "en-x-hbscabc", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("deva", "en-x-hbscdeva", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("dev2", "en-x-hbscdev2", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("dev3", "en-x-hbscdev3", HB_SCRIPT_INVALID);
+  test_script_tags_from_language ("copt", "en-x-hbotpap0-hbsccopt", HB_SCRIPT_INVALID);
+}
+
+static void
 test_ot_tag_script_indic (void)
 {
-  test_indic_tags ("bng2", "beng", HB_SCRIPT_BENGALI);
-  test_indic_tags ("dev2", "deva", HB_SCRIPT_DEVANAGARI);
-  test_indic_tags ("gjr2", "gujr", HB_SCRIPT_GUJARATI);
-  test_indic_tags ("gur2", "guru", HB_SCRIPT_GURMUKHI);
-  test_indic_tags ("knd2", "knda", HB_SCRIPT_KANNADA);
-  test_indic_tags ("mlm2", "mlym", HB_SCRIPT_MALAYALAM);
-  test_indic_tags ("ory2", "orya", HB_SCRIPT_ORIYA);
-  test_indic_tags ("tml2", "taml", HB_SCRIPT_TAMIL);
-  test_indic_tags ("tel2", "telu", HB_SCRIPT_TELUGU);
-  test_indic_tags ("mym2", "mymr", HB_SCRIPT_MYANMAR);
+  test_indic_tags ("bng3", "bng2", "beng", HB_SCRIPT_BENGALI);
+  test_indic_tags ("dev3", "dev2", "deva", HB_SCRIPT_DEVANAGARI);
+  test_indic_tags ("gjr3", "gjr2", "gujr", HB_SCRIPT_GUJARATI);
+  test_indic_tags ("gur3", "gur2", "guru", HB_SCRIPT_GURMUKHI);
+  test_indic_tags ("knd3", "knd2", "knda", HB_SCRIPT_KANNADA);
+  test_indic_tags ("mlm3", "mlm2", "mlym", HB_SCRIPT_MALAYALAM);
+  test_indic_tags ("ory3", "ory2", "orya", HB_SCRIPT_ORIYA);
+  test_indic_tags ("tml3", "tml2", "taml", HB_SCRIPT_TAMIL);
+  test_indic_tags ("tel3", "tel2", "telu", HB_SCRIPT_TELUGU);
+  test_indic_tags ("mym3", "mym2", "mymr", HB_SCRIPT_MYANMAR);
 }
 
 
@@ -144,10 +202,19 @@ test_language_two_way (const char *tag_s, const char *lang_s)
 {
   hb_language_t lang = hb_language_from_string (lang_s, -1);
   hb_tag_t tag = hb_tag_from_string (tag_s, -1);
+  hb_tag_t tag2;
+  unsigned int count = 1;
 
   g_test_message ("Testing language %s <-> tag %s", lang_s, tag_s);
 
-  g_assert_cmphex (tag, ==, hb_ot_tag_from_language (lang));
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_INVALID,
+                                      lang,
+                                      NULL, NULL, &count, &tag2);
+
+  if (count)
+    g_assert_cmphex (tag, ==, tag2);
+  else
+    g_assert_cmphex (tag, ==, HB_TAG_CHAR4 ("dflt"));
   g_assert (lang == hb_ot_tag_to_language (tag));
 }
 
@@ -156,10 +223,19 @@ test_tag_from_language (const char *tag_s, const char *lang_s)
 {
   hb_language_t lang = hb_language_from_string (lang_s, -1);
   hb_tag_t tag = hb_tag_from_string (tag_s, -1);
+  hb_tag_t tag2;
+  unsigned int count = 1;
 
   g_test_message ("Testing language %s -> tag %s", lang_s, tag_s);
 
-  g_assert_cmphex (tag, ==, hb_ot_tag_from_language (lang));
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_INVALID,
+                                      lang,
+                                      NULL, NULL, &count, &tag2);
+
+  if (count)
+    g_assert_cmphex (tag, ==, tag2);
+  else
+    g_assert_cmphex (tag, ==, HB_TAG_CHAR4 ("dflt"));
 }
 
 static void
@@ -174,6 +250,32 @@ test_tag_to_language (const char *tag_s, const char *lang_s)
 }
 
 static void
+test_tags_to_script_and_language (const char *script_tag_s,
+                                 const char *lang_tag_s,
+                                 const char *script_s,
+                                 const char *lang_s)
+{
+  hb_script_t actual_script[1];
+  hb_language_t actual_lang[1];
+  hb_tag_t script_tag = hb_tag_from_string (script_tag_s, -1);
+  hb_tag_t lang_tag = hb_tag_from_string (lang_tag_s, -1);
+  hb_ot_tags_to_script_and_language (script_tag, lang_tag, actual_script, actual_lang);
+  g_assert_cmphex (*actual_script, ==, hb_tag_from_string (script_s, -1));
+  g_assert_cmpstr (hb_language_to_string (*actual_lang), ==, lang_s);
+}
+
+static void
+test_ot_tags_to_script_and_language (void)
+{
+  test_tags_to_script_and_language ("DFLT", "ENG", "", "en-x-hbscdflt");
+  test_tags_to_script_and_language ("latn", "ENG", "Latn", "en");
+  test_tags_to_script_and_language ("deva", "MAR", "Deva", "mr-x-hbscdeva");
+  test_tags_to_script_and_language ("dev2", "MAR", "Deva", "mr-x-hbscdev2");
+  test_tags_to_script_and_language ("dev3", "MAR", "Deva", "mr");
+  test_tags_to_script_and_language ("qaa", "QTZ0", "Qaaa", "x-hbotqtz0-hbscqaa");
+}
+
+static void
 test_ot_tag_language (void)
 {
   g_assert_cmphex (HB_TAG_CHAR4 ("dflt"), ==, HB_OT_TAG_DEFAULT_LANGUAGE);
@@ -230,27 +332,27 @@ test_ot_tag_language (void)
 
   test_language_two_way ("TUA", "tru"); /* Turoyo Aramaic */
 
-  test_language_two_way ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */
-
   test_tag_from_language ("ZHS", "zh"); /* Chinese */
   test_tag_from_language ("ZHS", "zh-cn"); /* Chinese (China) */
   test_tag_from_language ("ZHS", "zh-sg"); /* Chinese (Singapore) */
   test_tag_from_language ("ZHH", "zh-mo"); /* Chinese (Macao) */
   test_tag_from_language ("ZHH", "zh-hant-mo"); /* Chinese (Macao) */
-  test_tag_from_language ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */
+  test_language_two_way ("ZHH", "zh-HK"); /* Chinese (Hong Kong) */
   test_tag_from_language ("ZHH", "zH-HanT-hK"); /* Chinese (Hong Kong) */
   test_tag_from_language ("ZHT", "zh-tw"); /* Chinese (Taiwan) */
-  test_tag_from_language ("ZHS", "zh-Hans"); /* Chinese (Simplified) */
-  test_tag_from_language ("ZHT", "zh-Hant"); /* Chinese (Traditional) */
+  test_language_two_way ("ZHS", "zh-Hans"); /* Chinese (Simplified) */
+  test_language_two_way ("ZHT", "zh-Hant"); /* Chinese (Traditional) */
   test_tag_from_language ("ZHS", "zh-xx"); /* Chinese (Other) */
 
+  test_tag_from_language ("ZHS", "zh-Hans-TW");
+
+  test_tag_from_language ("ZHH", "yue");
+  test_tag_from_language ("ZHH", "yue-Hant");
+  test_tag_from_language ("ZHS", "yue-Hans");
+
   test_tag_from_language ("ZHS", "zh"); /* Chinese */
   test_tag_from_language ("ZHS", "zh-xx");
 
-  test_tag_to_language ("ZHS", "zh-Hans");
-  test_tag_to_language ("ZHT", "zh-Hant");
-  test_tag_to_language ("ZHP", "x-hbotzhp");
-
   test_language_two_way ("ABC", "x-hbotabc");
   test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc-zxc");
   test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc");
@@ -262,39 +364,64 @@ test_ot_tag_language (void)
   test_tag_from_language ("XYZ", "xyz"); /* Unknown ISO 639-3 */
   test_tag_from_language ("XYZ", "xyz-qw"); /* Unknown ISO 639-3 */
 
+  /*
+   * Invalid input. The precise answer does not matter, as long as it
+   * does not crash or get into an infinite loop.
+   */
+  test_tag_from_language ("IPPH", "-fonipa");
+
+  /*
+   * Tags that contain "-fonipa" as a substring but which do not contain
+   * the subtag "fonipa".
+   */
+  test_tag_from_language ("ENG", "en-fonipax");
+  test_tag_from_language ("ENG", "en-x-fonipa");
+  test_tag_from_language ("ENG", "en-a-fonipa");
+  test_tag_from_language ("ENG", "en-a-qwe-b-fonipa");
+
   /* International Phonetic Alphabet */
   test_tag_from_language ("IPPH", "en-fonipa");
+  test_tag_from_language ("IPPH", "en-fonipax-fonipa");
   test_tag_from_language ("IPPH", "rm-CH-fonipa-sursilv-x-foobar");
-  test_tag_from_language ("IPPH", "und-fonipa");
+  test_language_two_way ("IPPH", "und-fonipa");
   test_tag_from_language ("IPPH", "zh-fonipa");
-  test_tag_to_language ("IPPH", "und-fonipa");
 
   /* North American Phonetic Alphabet (Americanist Phonetic Notation) */
   test_tag_from_language ("APPH", "en-fonnapa");
   test_tag_from_language ("APPH", "chr-fonnapa");
-  test_tag_from_language ("APPH", "und-fonnapa");
-  test_tag_to_language ("APPH", "und-fonnapa");
+  test_language_two_way ("APPH", "und-fonnapa");
+
+  /* Khutsuri Georgian */
+  test_tag_from_language ("KGE", "ka-Geok");
+  test_language_two_way ("KGE", "und-Geok");
+
+  /* Irish Traditional */
+  test_language_two_way ("IRT", "ga-Latg");
+
+  /* Moldavian */
+  test_language_two_way ("MOL", "ro-MD");
+
+  /* Polytonic Greek */
+  test_language_two_way ("PGR", "el-polyton");
+  test_tag_from_language ("PGR", "el-CY-polyton");
 
   /* Estrangela Syriac */
   test_tag_from_language ("SYRE", "aii-Syre");
   test_tag_from_language ("SYRE", "de-Syre");
   test_tag_from_language ("SYRE", "syr-Syre");
-  test_tag_from_language ("SYRE", "und-Syre");
-  test_tag_to_language ("SYRE", "und-Syre");
+  test_language_two_way ("SYRE", "und-Syre");
 
   /* Western Syriac */
   test_tag_from_language ("SYRJ", "aii-Syrj");
   test_tag_from_language ("SYRJ", "de-Syrj");
   test_tag_from_language ("SYRJ", "syr-Syrj");
-  test_tag_from_language ("SYRJ", "und-Syrj");
-  test_tag_to_language ("SYRJ", "und-Syrj");
+  test_language_two_way ("SYRJ", "und-Syrj");
 
   /* Eastern Syriac */
   test_tag_from_language ("SYRN", "aii-Syrn");
   test_tag_from_language ("SYRN", "de-Syrn");
   test_tag_from_language ("SYRN", "syr-Syrn");
-  test_tag_from_language ("SYRN", "und-Syrn");
-  test_tag_to_language ("SYRN", "und-Syrn");
+  test_language_two_way ("SYRN", "und-Syrn");
 
   /* Test that x-hbot overrides the base language */
   test_tag_from_language ("ABC", "fa-x-hbotabc-zxc");
@@ -303,6 +430,81 @@ test_ot_tag_language (void)
   test_tag_from_language ("ABC", "zh-cn-x-hbotabc-zxc");
   test_tag_from_language ("ABC", "zh-xy-x-hbotabc-zxc");
   test_tag_from_language ("ABC", "xyz-xy-x-hbotabc-zxc");
+
+  /* Unnormalized BCP 47 tags */
+  test_tag_from_language ("ARA", "ar-aao");
+  test_tag_from_language ("JBO", "art-lojban");
+  test_tag_from_language ("KOK", "kok-gom");
+  test_tag_from_language ("LTZ", "i-lux");
+  test_tag_from_language ("MNG", "drh");
+  test_tag_from_language ("MOR", "ar-ary");
+  test_tag_from_language ("MOR", "ar-ary-DZ");
+  test_tag_from_language ("NOR", "no-bok");
+  test_tag_from_language ("NYN", "no-nyn");
+  test_tag_from_language ("ZHS", "i-hak");
+  test_tag_from_language ("ZHS", "zh-guoyu");
+  test_tag_from_language ("ZHS", "zh-min");
+  test_tag_from_language ("ZHS", "zh-min-nan");
+  test_tag_from_language ("ZHS", "zh-xiang");
+
+  /* A UN M.49 region code, not an extended language subtag */
+  test_tag_from_language ("ARA", "ar-001");
+
+  /* An invalid tag */
+  test_tag_from_language ("TRK", "tr@foo=bar");
+}
+
+static void
+test_tags (hb_script_t  script,
+          const char  *lang_s,
+          unsigned int script_count,
+          unsigned int language_count,
+          unsigned int expected_script_count,
+          unsigned int expected_language_count,
+          ...)
+{
+  va_list expected_tags;
+  unsigned int i;
+  hb_tag_t *script_tags = malloc (script_count * sizeof (hb_tag_t));
+  hb_tag_t *language_tags = malloc (language_count * sizeof (hb_tag_t));
+  hb_language_t lang;
+  g_assert (script_tags);
+  g_assert (language_tags);
+  lang = hb_language_from_string (lang_s, -1);
+  va_start (expected_tags, expected_language_count);
+
+  hb_ot_tags_from_script_and_language (script, lang, &script_count, script_tags, &language_count, language_tags);
+
+  g_assert_cmpuint (script_count, ==, expected_script_count);
+  g_assert_cmpuint (language_count, ==, expected_language_count);
+
+  for (i = 0; i < script_count + language_count; i++)
+  {
+    hb_tag_t expected_tag = hb_tag_from_string (va_arg (expected_tags, const char *), -1);
+    hb_tag_t actual_tag = i < script_count ? script_tags[i] : language_tags[i - script_count];
+    g_assert_cmphex (actual_tag, ==, expected_tag);
+  }
+
+  free (script_tags);
+  free (language_tags);
+  va_end (expected_tags);
+}
+
+static void
+test_ot_tag_full (void)
+{
+  test_tags (HB_SCRIPT_INVALID, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "ENG");
+  test_tags (HB_SCRIPT_INVALID, "en-x-hbscdflt", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "DFLT", "ENG");
+  test_tags (HB_SCRIPT_LATIN, "en", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "latn", "ENG");
+  test_tags (HB_SCRIPT_LATIN, "en", 0, 0, 0, 0);
+  test_tags (HB_SCRIPT_INVALID, "und-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
+  test_tags (HB_SCRIPT_INVALID, "en-fonnapa", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "APPH");
+  test_tags (HB_SCRIPT_INVALID, "x-hbot1234-hbsc5678", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
+  test_tags (HB_SCRIPT_INVALID, "x-hbsc5678-hbot1234", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 1, 1, "5678", "1234");
+  test_tags (HB_SCRIPT_MALAYALAM, "ml", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 3, 2, "mlm3", "mlm2", "mlym", "MAL", "MLR");
+  test_tags (HB_SCRIPT_MALAYALAM, "ml", 1, 1, 1, 1, "mlm3", "MAL");
+  test_tags (HB_SCRIPT_INVALID, "xyz", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 1, "XYZ");
+  test_tags (HB_SCRIPT_INVALID, "xy", HB_OT_MAX_TAGS_PER_SCRIPT, HB_OT_MAX_TAGS_PER_LANGUAGE, 0, 0);
 }
 
 int
@@ -312,9 +514,14 @@ main (int argc, char **argv)
 
   hb_test_add (test_ot_tag_script_degenerate);
   hb_test_add (test_ot_tag_script_simple);
+  hb_test_add (test_ot_tag_script_from_language);
   hb_test_add (test_ot_tag_script_indic);
 
+  hb_test_add (test_ot_tags_to_script_and_language);
+
   hb_test_add (test_ot_tag_language);
 
+  hb_test_add (test_ot_tag_full);
+
   return hb_test_run();
 }
index 338a610..aa2b388 100644 (file)
@@ -118,6 +118,9 @@ test_set_basic (void)
   g_assert (!hb_set_has (s, 801));
   g_assert (!hb_set_has (s, 802));
 
+  hb_set_del (s, 800);
+  g_assert (!hb_set_has (s, 800));
+
   hb_set_destroy (s);
 }
 
@@ -262,6 +265,7 @@ test_set_algebra (void)
 
   hb_set_destroy (s);
   hb_set_destroy (o);
+  hb_set_destroy (o2);
 }
 
 static void
@@ -380,10 +384,6 @@ test_set_empty (void)
 
   test_empty (b);
 
-  hb_set_invert (b);
-
-  test_empty (b);
-
   g_assert (!hb_set_allocation_successful (b));
 
   hb_set_clear (b);
index 6232e73..146cf0f 100644 (file)
@@ -41,9 +41,9 @@
 static const char test_data[] = "test\0data";
 
 static hb_position_t
-glyph_h_advance_func (hb_font_t *font, void *font_data,
+glyph_h_advance_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
                      hb_codepoint_t glyph,
-                     void *user_data)
+                     void *user_data HB_UNUSED)
 {
   switch (glyph) {
   case 1: return 10;
@@ -54,10 +54,10 @@ glyph_h_advance_func (hb_font_t *font, void *font_data,
 }
 
 static hb_bool_t
-glyph_func (hb_font_t *font, void *font_data,
-           hb_codepoint_t unicode, hb_codepoint_t variant_selector,
+glyph_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
+           hb_codepoint_t unicode,
            hb_codepoint_t *glyph,
-           void *user_data)
+           void *user_data HB_UNUSED)
 {
   switch (unicode) {
   case 'T': *glyph = 1; return TRUE;
@@ -68,9 +68,9 @@ glyph_func (hb_font_t *font, void *font_data,
 }
 
 static hb_position_t
-glyph_h_kerning_func (hb_font_t *font, void *font_data,
+glyph_h_kerning_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
                      hb_codepoint_t left, hb_codepoint_t right,
-                     void *user_data)
+                     void *user_data HB_UNUSED)
 {
   if (left == 1 && right == 2)
     return -2;
@@ -101,7 +101,7 @@ test_shape (void)
 
   ffuncs = hb_font_funcs_create ();
   hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
-  hb_font_funcs_set_glyph_func (ffuncs, glyph_func, malloc (10), free);
+  hb_font_funcs_set_nominal_glyph_func (ffuncs, glyph_func, malloc (10), free);
   hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL);
   hb_font_set_funcs (font, ffuncs, NULL, NULL);
   hb_font_funcs_destroy (ffuncs);
diff --git a/test/api/test-subset-cff1.c b/test/api/test-subset-cff1.c
new file mode 100644 (file)
index 0000000..3ee2702
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for CFF subsetting */
+
+static void
+test_subset_cff1_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/SourceSansPro-Regular.abc.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_cff1 (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansPro-Regular.ac.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff1_strip_hints (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansPro-Regular.ac.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C', 'F', 'F', ' '));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff1_desubr (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansPro-Regular.ac.nosubrs.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_desubroutinize (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff1_desubr_strip_hints (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansPro-Regular.ac.nosubrs.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  hb_subset_input_set_desubroutinize (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C', 'F', 'F', ' '));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff1_j (void)
+{
+  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
+  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_41_3041_4c2e_subset;
+  hb_set_add (codepoints, 0x41);
+  hb_set_add (codepoints, 0x4C2E);
+  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_41_3041_4c2e_subset);
+  hb_face_destroy (face_41_3041_4c2e);
+  hb_face_destroy (face_41_4c2e);
+}
+
+static void
+test_subset_cff1_j_strip_hints (void)
+{
+  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
+  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_41_3041_4c2e_subset;
+  hb_subset_input_t *input;
+  hb_set_add (codepoints, 0x41);
+  hb_set_add (codepoints, 0x4C2E);
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_41_3041_4c2e_subset);
+  hb_face_destroy (face_41_3041_4c2e);
+  hb_face_destroy (face_41_4c2e);
+}
+
+static void
+test_subset_cff1_j_desubr (void)
+{
+  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
+  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.nosubrs.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_41_3041_4c2e_subset;
+  hb_subset_input_t *input;
+  hb_set_add (codepoints, 0x41);
+  hb_set_add (codepoints, 0x4C2E);
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_desubroutinize (input, true);
+  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_41_3041_4c2e_subset);
+  hb_face_destroy (face_41_3041_4c2e);
+  hb_face_destroy (face_41_4c2e);
+}
+
+static void
+test_subset_cff1_j_desubr_strip_hints (void)
+{
+  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
+  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_41_3041_4c2e_subset;
+  hb_subset_input_t *input;
+  hb_set_add (codepoints, 0x41);
+  hb_set_add (codepoints, 0x4C2E);
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  hb_subset_input_set_desubroutinize (input, true);
+  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_41_3041_4c2e_subset);
+  hb_face_destroy (face_41_3041_4c2e);
+  hb_face_destroy (face_41_4c2e);
+}
+
+static void
+test_subset_cff1_expert (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_expert.otf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_expert.2D,F6E9,FB00.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_test;
+  hb_set_add (codepoints, 0x2D);
+  hb_set_add (codepoints, 0xF6E9);
+  hb_set_add (codepoints, 0xFB00);
+  face_test = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_test);
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face);
+}
+
+static void
+test_subset_cff1_seac (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_seac.C0.otf");
+  hb_face_t *face_test;
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_set_add (codepoints, 0xC0);  /* Agrave */
+  face_test = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_test);
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face);
+}
+
+static void
+test_subset_cff1_dotsection (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_dotsect.otf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_dotsect.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_test;
+  hb_set_add (codepoints, 0x69);  /* i */
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  face_test = hb_subset_test_create_subset (face, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));
+
+  hb_face_destroy (face_test);
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_cff1_noop);
+  hb_test_add (test_subset_cff1);
+  hb_test_add (test_subset_cff1_strip_hints);
+  hb_test_add (test_subset_cff1_desubr);
+  hb_test_add (test_subset_cff1_desubr_strip_hints);
+  hb_test_add (test_subset_cff1_j);
+  hb_test_add (test_subset_cff1_j_strip_hints);
+  hb_test_add (test_subset_cff1_j_desubr);
+  hb_test_add (test_subset_cff1_j_desubr_strip_hints);
+  hb_test_add (test_subset_cff1_expert);
+  hb_test_add (test_subset_cff1_seac);
+  hb_test_add (test_subset_cff1_dotsection);
+
+  return hb_test_run ();
+}
diff --git a/test/api/test-subset-cff2.c b/test/api/test-subset-cff2.c
new file mode 100644 (file)
index 0000000..9367965
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2018 Adobe 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.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for CFF2 subsetting */
+
+static void
+test_subset_cff2_noop (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file("fonts/AdobeVFPrototype.abc.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('C','F','F','2'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+}
+
+static void
+test_subset_cff2 (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C','F','F','2'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff2_strip_hints (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C', 'F', 'F', '2'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff2_desubr (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.nosubrs.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_desubroutinize (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C', 'F', 'F', '2'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+static void
+test_subset_cff2_desubr_strip_hints (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/AdobeVFPrototype.abc.otf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/AdobeVFPrototype.ac.nosubrs.nohints.otf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_subset_input_t *input;
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_desubroutinize (input, true);
+  hb_subset_input_set_drop_hints (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C', 'F', 'F', '2'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_cff2_noop);
+  hb_test_add (test_subset_cff2);
+  hb_test_add (test_subset_cff2_strip_hints);
+  hb_test_add (test_subset_cff2_desubr);
+  hb_test_add (test_subset_cff2_desubr_strip_hints);
+
+  return hb_test_run ();
+}
index 84d34bc..74e91ca 100644 (file)
@@ -32,8 +32,8 @@
 static void
 test_subset_cmap (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -52,7 +52,7 @@ test_subset_cmap (void)
 static void
 test_subset_cmap_non_consecutive_glyphs (void)
 {
-  hb_face_t *face = hb_subset_test_open_font ("fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf");
+  hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_subset;
@@ -74,7 +74,7 @@ test_subset_cmap_non_consecutive_glyphs (void)
 static void
 test_subset_cmap_noop (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
diff --git a/test/api/test-subset-codepoints.c b/test/api/test-subset-codepoints.c
deleted file mode 100644 (file)
index 3bd1fe0..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#include "hb-test.h"
-#include "hb-subset-test.h"
-
-static void
-test_get_all_codepoints_format4 (void)
-{
-  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format4.ttf");
-  hb_set_t *codepoints = hb_set_create();
-
-  hb_subset_get_all_codepoints (face, codepoints);
-
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x61, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x62, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x63, ==, cp);
-  g_assert (!hb_set_next (codepoints, &cp));
-
-  hb_set_destroy (codepoints);
-  hb_face_destroy (face);
-}
-
-static void
-test_get_all_codepoints_format12 (void)
-{
-  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format12.ttf");
-  hb_set_t *codepoints = hb_set_create();
-
-  hb_subset_get_all_codepoints (face, codepoints);
-
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x61, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x62, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x63, ==, cp);
-  g_assert (!hb_set_next (codepoints, &cp));
-
-  hb_set_destroy (codepoints);
-  hb_face_destroy (face);
-}
-
-static void
-test_get_all_codepoints (void)
-{
-  hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
-  hb_set_t *codepoints = hb_set_create();
-
-  hb_subset_get_all_codepoints (face, codepoints);
-
-  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x61, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x62, ==, cp);
-  g_assert (hb_set_next (codepoints, &cp));
-  g_assert_cmpuint (0x63, ==, cp);
-  g_assert (!hb_set_next (codepoints, &cp));
-
-  hb_set_destroy (codepoints);
-  hb_face_destroy (face);
-}
-
-int
-main (int argc, char **argv)
-{
-  hb_test_init (&argc, &argv);
-
-  hb_test_add (test_get_all_codepoints);
-  hb_test_add (test_get_all_codepoints_format4);
-  hb_test_add (test_get_all_codepoints_format12);
-
-  return hb_test_run();
-}
index e4440e0..0e5c293 100644 (file)
@@ -60,8 +60,8 @@ static void check_maxp_num_glyphs (hb_face_t *face, uint16_t expected_num_glyphs
 static void
 test_subset_glyf (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
@@ -82,8 +82,8 @@ test_subset_glyf (void)
 static void
 test_subset_glyf_with_components (void)
 {
-  hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf");
-  hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.subset.ttf");
+  hb_face_t *face_components = hb_test_open_font_file ("fonts/Roboto-Regular.components.ttf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/Roboto-Regular.components.subset.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_generated_subset;
@@ -103,18 +103,20 @@ test_subset_glyf_with_components (void)
 static void
 test_subset_glyf_with_gsub (void)
 {
-  hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
-  hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fi.ttf");
+  hb_face_t *face_fil = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fil.ttf");
+  hb_face_t *face_fi = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fi.ttf");
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 102); // f
   hb_set_add (codepoints, 105); // i
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
-  *hb_subset_input_drop_ot_layout (input) = false;
+  hb_subset_input_set_drop_layout (input, false);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input);
+  face_subset = hb_subset_test_create_subset (face_fil, input);
 
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a'));
@@ -128,18 +130,20 @@ test_subset_glyf_with_gsub (void)
 static void
 test_subset_glyf_without_gsub (void)
 {
-  hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
-  hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.nogsub.fi.ttf");
+  hb_face_t *face_fil = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fil.ttf");
+  hb_face_t *face_fi = hb_test_open_font_file ("fonts/Roboto-Regular.nogsub.fi.ttf");
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 102); // f
   hb_set_add (codepoints, 105); // i
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
-  *hb_subset_input_drop_ot_layout (input) = true;
+  hb_subset_input_set_drop_layout (input, true);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face_fil, input);
+  face_subset = hb_subset_test_create_subset (face_fil, input);
 
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_fi, face_subset, HB_TAG ('l','o','c', 'a'));
@@ -153,7 +157,7 @@ test_subset_glyf_without_gsub (void)
 static void
 test_subset_glyf_noop (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
@@ -174,8 +178,8 @@ test_subset_glyf_noop (void)
 static void
 test_subset_glyf_strip_hints_simple (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.nohints.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.nohints.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_subset_input_t *input;
@@ -183,7 +187,7 @@ test_subset_glyf_strip_hints_simple (void)
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'c');
   input = hb_subset_test_create_input (codepoints);
-  *hb_subset_input_drop_hints(input) = true;
+  hb_subset_input_set_drop_hints (input, true);
   face_abc_subset = hb_subset_test_create_subset (face_abc, input);
   hb_set_destroy (codepoints);
 
@@ -199,15 +203,15 @@ test_subset_glyf_strip_hints_simple (void)
 static void
 test_subset_glyf_strip_hints_composite (void)
 {
-  hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf");
-  hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.1fc.nohints.ttf");
+  hb_face_t *face_components = hb_test_open_font_file ("fonts/Roboto-Regular.components.ttf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/Roboto-Regular.components.1fc.nohints.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_subset_input_t *input;
   hb_face_t *face_generated_subset;
   hb_set_add (codepoints, 0x1fc);
   input = hb_subset_test_create_input (codepoints);
-  *hb_subset_input_drop_hints(input) = true;
+  hb_subset_input_set_drop_hints (input, true);
 
   face_generated_subset = hb_subset_test_create_subset (face_components, input);
   hb_set_destroy (codepoints);
@@ -224,7 +228,7 @@ test_subset_glyf_strip_hints_composite (void)
 static void
 test_subset_glyf_strip_hints_invalid (void)
 {
-  hb_face_t *face = hb_subset_test_open_font ("fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
 
   hb_set_t *codepoints = hb_set_create();
   const hb_codepoint_t text[] =
@@ -233,16 +237,19 @@ test_subset_glyf_strip_hints_invalid (void)
     '3', '@', '_', '%', '&', ')', '*', '$', '!'
   };
   unsigned int i;
+  hb_subset_input_t *input;
+  hb_face_t *face_subset;
+
   for (i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++)
   {
     hb_set_add (codepoints, text[i]);
   }
 
-  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
-  *hb_subset_input_drop_hints(input) = true;
+  input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_drop_hints (input, true);
   hb_set_destroy (codepoints);
 
-  hb_face_t *face_subset = hb_subset_test_create_subset (face, input);
+  face_subset = hb_subset_test_create_subset (face, input);
   g_assert (face_subset);
   g_assert (face_subset == hb_face_get_empty ());
 
index c78009b..44e579a 100644 (file)
@@ -33,8 +33,8 @@
 static void
 test_subset_hdmx_simple_subset (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -51,23 +51,42 @@ test_subset_hdmx_simple_subset (void)
 }
 
 static void
+test_subset_hdmx_multiple_device_records (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.abc.ttf");
+  hb_face_t *face_a = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.a.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 'a');
+  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('h','d','m','x'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_a);
+}
+
+static void
 test_subset_hdmx_invalid (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
@@ -75,21 +94,21 @@ test_subset_hdmx_invalid (void)
 static void
 test_subset_hdmx_fails_sanitize (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
@@ -97,7 +116,7 @@ test_subset_hdmx_fails_sanitize (void)
 static void
 test_subset_hdmx_noop (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
@@ -119,6 +138,7 @@ main (int argc, char **argv)
   hb_test_init (&argc, &argv);
 
   hb_test_add (test_subset_hdmx_simple_subset);
+  hb_test_add (test_subset_hdmx_multiple_device_records);
   hb_test_add (test_subset_hdmx_invalid);
   hb_test_add (test_subset_hdmx_fails_sanitize);
   hb_test_add (test_subset_hdmx_noop);
index 0ed6256..1b51dc2 100644 (file)
@@ -47,8 +47,8 @@ static void check_num_hmetrics(hb_face_t *face, uint16_t expected_num_hmetrics)
 static void
 test_subset_hmtx_simple_subset (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -69,8 +69,8 @@ test_subset_hmtx_simple_subset (void)
 static void
 test_subset_hmtx_monospace (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ac.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Inconsolata-Regular.ac.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -91,8 +91,8 @@ test_subset_hmtx_monospace (void)
 static void
 test_subset_hmtx_keep_num_metrics (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.widerc.ttf");
-  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ac.widerc.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.widerc.ttf");
+  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Inconsolata-Regular.ac.widerc.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -112,8 +112,8 @@ test_subset_hmtx_keep_num_metrics (void)
 static void
 test_subset_hmtx_decrease_num_metrics (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.widerc.ttf");
-  hb_face_t *face_ab = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ab.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.widerc.ttf");
+  hb_face_t *face_ab = hb_test_open_font_file ("fonts/Inconsolata-Regular.ab.ttf");
 
   hb_set_t *codepoints = hb_set_create ();
   hb_face_t *face_abc_subset;
@@ -133,7 +133,7 @@ test_subset_hmtx_decrease_num_metrics (void)
 static void
 test_subset_hmtx_noop (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
@@ -153,7 +153,8 @@ test_subset_hmtx_noop (void)
 static void
 test_subset_invalid_hmtx (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
+  hb_face_t *subset;
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@@ -161,13 +162,11 @@ test_subset_invalid_hmtx (void)
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
index de63a3f..dfc9461 100644 (file)
@@ -31,8 +31,8 @@
 static void
 test_subset_os2 (void)
 {
-  hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
-  hb_face_t *face_b = hb_subset_test_open_font("fonts/Roboto-Regular.b.ttf");
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_b = hb_test_open_font_file ("fonts/Roboto-Regular.b.ttf");
 
   hb_set_t *codepoints = hb_set_create();
   hb_face_t *face_abc_subset;
index 948b18a..e31b01e 100644 (file)
 static void
 test_post_drops_glyph_names (void)
 {
-  hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
-  hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 0x660E);
 
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_subset, face_full_subset, HB_TAG ('p','o','s','t'));
index 437f0c2..24a4a76 100644 (file)
@@ -46,13 +46,14 @@ static void check_num_vmetrics(hb_face_t *face, uint16_t expected_num_vmetrics)
 static void
 test_subset_vmtx_simple_subset (void)
 {
-  hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
-  hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
+  hb_face_t *face_subset = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 0x660E);
 
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_vmetrics(face_full_subset, 1); /* nothing has same width */
@@ -66,7 +67,8 @@ test_subset_vmtx_simple_subset (void)
 static void
 test_subset_vmtx_noop (void)
 {
-  hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
+  hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
+  hb_face_t *face_full_subset;
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 0x660E);
@@ -75,7 +77,7 @@ test_subset_vmtx_noop (void)
   hb_set_add (codepoints, 0x5EA6);
   hb_set_add (codepoints, 0x8F38);
   hb_set_add (codepoints, 0x6E05);
-  hb_face_t *face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
+  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_vmetrics(face_full_subset, 1); /* all have the same width */
index 6d2bf06..85e4fdf 100644 (file)
 static void
 test_subset_32_tables (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653");
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset != hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
@@ -54,21 +54,21 @@ test_subset_32_tables (void)
 static void
 test_subset_no_inf_loop (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016");
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
@@ -76,21 +76,21 @@ test_subset_no_inf_loop (void)
 static void
 test_subset_crash (void)
 {
-  hb_face_t *face = hb_subset_test_open_font("fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249");
+  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249");
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_face_t *subset;
+
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
 
-  hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_face_t *subset = hb_subset (face, profile, input);
+  subset = hb_subset (face, input);
   g_assert (subset);
   g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
   hb_face_destroy (subset);
   hb_face_destroy (face);
 }
index 88f12e7..6195bb2 100644 (file)
@@ -160,69 +160,6 @@ static const test_pair_t combining_class_tests_more[] =
   { 0x111111, 0 }
 };
 
-static const test_pair_t eastasian_width_tests[] =
-{
-  /* Neutral */
-  {   0x0000, 1 },
-  {   0x0483, 1 },
-  {   0x0641, 1 },
-  {   0xFFFC, 1 },
-  {  0x10000, 1 },
-  {  0xE0001, 1 },
-
-  /* Narrow */
-  {   0x0020, 1 },
-  {   0x0041, 1 },
-  {   0x27E6, 1 },
-
-  /* Halfwidth */
-  {   0x20A9, 1 },
-  {   0xFF61, 1 },
-  {   0xFF69, 1 },
-  {   0xFFEE, 1 },
-
-  /* Ambiguous */
-  {   0x00A1, 1 },
-  {   0x00D8, 1 },
-  {   0x02DD, 1 },
-  {  0xE0100, 1 },
-  { 0x100000, 1 },
-
-  /* Fullwidth */
-  {   0x3000, 2 },
-  {   0xFF60, 2 },
-
-  /* Wide */
-  {   0x2329, 2 },
-  {   0x3001, 2 },
-  {   0xFE69, 2 },
-  {  0x30000, 2 },
-  {  0x3FFFD, 2 },
-
-  { 0x111111, 1 }
-};
-static const test_pair_t eastasian_width_tests_more[] =
-{
-  /* Default Wide blocks */
-  {   0x4DBF, 2 },
-  {   0x9FFF, 2 },
-  {   0xFAFF, 2 },
-  {  0x2A6DF, 2 },
-  {  0x2B73F, 2 },
-  {  0x2B81F, 2 },
-  {  0x2FA1F, 2 },
-
-  /* Uniode-5.2 character additions */
-  /* Wide */
-  {   0x115F, 2 },
-
-  /* Uniode-6.0 character additions */
-  /* Wide */
-  {  0x2B740, 2 },
-  {  0x1B000, 2 },
-
-  { 0x111111, 1 }
-};
 
 static const test_pair_t general_category_tests[] =
 {
@@ -469,7 +406,6 @@ typedef struct {
 static const property_t properties[] =
 {
   PROPERTY (combining_class, 0),
-  PROPERTY (eastasian_width, 1),
   PROPERTY (general_category, (unsigned int) HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER),
   PROPERTY (mirroring, RETURNS_UNICODE_ITSELF),
   PROPERTY (script, (unsigned int) HB_SCRIPT_UNKNOWN)
@@ -645,18 +581,18 @@ typedef struct {
 } data_fixture_t;
 
 static void
-data_fixture_init (data_fixture_t *f, gconstpointer user_data)
+data_fixture_init (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
 {
   f->data[0].value = MAGIC0;
   f->data[1].value = MAGIC1;
 }
 static void
-data_fixture_finish (data_fixture_t *f, gconstpointer user_data)
+data_fixture_finish (data_fixture_t *f HB_UNUSED, gconstpointer user_data HB_UNUSED)
 {
 }
 
 static void
-test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data)
+test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
 {
   hb_unicode_funcs_t *uf, *aa;
 
@@ -678,7 +614,7 @@ test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data)
 }
 
 static void
-test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data)
+test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
 {
   hb_unicode_funcs_t *uf, *aa;
 
@@ -697,7 +633,7 @@ test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data)
 }
 
 static void
-test_unicode_subclassing_deep (data_fixture_t *f, gconstpointer user_data)
+test_unicode_subclassing_deep (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
 {
   hb_unicode_funcs_t *uf, *aa;
 
@@ -786,7 +722,6 @@ test_unicode_normalization (gconstpointer user_data)
 {
   hb_unicode_funcs_t *uf = (hb_unicode_funcs_t *) user_data;
   gunichar a, b, ab;
-  hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN];
 
 
   /* Test compose() */
@@ -849,56 +784,6 @@ test_unicode_normalization (gconstpointer user_data)
   g_assert (hb_unicode_decompose (uf, 0xD4CC, &a, &b) && a == 0x1111 && b == 0x1171);
   g_assert (hb_unicode_decompose (uf, 0xCE31, &a, &b) && a == 0xCE20 && b == 0x11B8);
   g_assert (hb_unicode_decompose (uf, 0xCE20, &a, &b) && a == 0x110E && b == 0x1173);
-
-
-  /* Test decompose_compatibility() */
-
-  /* Not decomposable */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x0041, decomposed) == 0);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x1F632, decomposed) == 0);
-
-  /* Singletons */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x00B5, decomposed) == 1 && decomposed[0] == 0x03BC);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x03D6, decomposed) == 1 && decomposed[0] == 0x03C0);
-
-  /* Arabic compatibility */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0xFB54, decomposed) == 1 && decomposed[0] == 0x067B);
-
-  /* Longest decomposition ever */
-  g_assert (18 <= HB_UNICODE_MAX_DECOMPOSITION_LEN);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0xFDFA, decomposed) == 18 && decomposed[17] == 0x0645);
-
-  /* Note: we deliberately don't test characters that have canonical decompositions but no
-   * compatibility decomposition against the decompose_compatibility() function as that we
-   * leave up to implementations (for now). */
-
-  /* Spaces */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2002, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2003, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2004, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2005, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2006, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2008, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2009, decomposed) == 1 && decomposed[0] == 0x0020);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x200A, decomposed) == 1 && decomposed[0] == 0x0020);
-
-  /* Pairs */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x0587, decomposed) == 2 &&
-            decomposed[0] == 0x0565 && decomposed[1] == 0x0582);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2017, decomposed) == 2 &&
-            decomposed[0] == 0x0020 && decomposed[1] == 0x0333);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2025, decomposed) == 2 &&
-            decomposed[0] == 0x002E && decomposed[1] == 0x002E);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2033, decomposed) == 2 &&
-            decomposed[0] == 0x2032 && decomposed[1] == 0x2032);
-
-  /* Triples */
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2026, decomposed) == 3 &&
-            decomposed[0] == 0x002E && decomposed[1] == 0x002E && decomposed[2] == 0x002E);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x2034, decomposed) == 3 &&
-            decomposed[0] == 0x2032 && decomposed[1] == 0x2032 && decomposed[2] == 0x2032);
-  g_assert (hb_unicode_decompose_compatibility (uf, 0x213B, decomposed) == 3 &&
-            decomposed[0] == 0x0046 && decomposed[1] == 0x0041 && decomposed[2] == 0x0058);
 }
 
 
index 2a45ef6..577d13c 100644 (file)
@@ -2,7 +2,6 @@ if (HB_CHECK)
   file (READ "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am" MAKEFILEAM)
   extract_make_variable (hb_shape_fuzzer_SOURCES ${MAKEFILEAM})
   extract_make_variable (hb_subset_fuzzer_SOURCES ${MAKEFILEAM})
-  extract_make_variable (hb_subset_get_codepoints_fuzzer_SOURCES ${MAKEFILEAM})
 
   # TODO: enable these two
   #extract_make_variable (FUZZING_CPPFLAGS ${MAKEFILEAM}) # extracting regex fail
@@ -16,17 +15,13 @@ if (HB_CHECK)
   add_executable (hb-subset-fuzzer ${hb_subset_fuzzer_SOURCES})
   target_link_libraries (hb-subset-fuzzer harfbuzz-subset)
 
-  add_executable (hb-subset-get-codepoints-fuzzer ${hb_subset_get_codepoints_fuzzer_SOURCES})
-  target_link_libraries (hb-subset-get-codepoints-fuzzer harfbuzz-subset)
-
   target_compile_definitions(hb-shape-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
   target_compile_definitions(hb-subset-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
-  target_compile_definitions(hb-subset-get-codepoints-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
 
   add_test (NAME hb-shape-fuzzer
     COMMAND "${PYTHON_EXECUTABLE}" run-shape-fuzzer-tests.py $<TARGET_FILE:hb-shape-fuzzer>
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
   add_test (NAME hb-subset-fuzzer
-    COMMAND "${PYTHON_EXECUTABLE}" run-subset-fuzzer-tests.py $<TARGET_FILE:hb-subset-fuzzer> $<TARGET_FILE:hb-subset-get-codepoints-fuzzer>
+    COMMAND "${PYTHON_EXECUTABLE}" run-subset-fuzzer-tests.py $<TARGET_FILE:hb-subset-fuzzer>
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 endif ()
index 5af5a73..a77df70 100644 (file)
@@ -8,22 +8,24 @@ MAINTAINERCLEANFILES =
 
 # Convenience targets:
 lib:
-       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src fuzzing
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
-$(top_builddir)/src/libharfbuzz-fuzzing.la: lib
-$(top_builddir)/src/libharfbuzz-subset-fuzzing.la: lib
+$(top_builddir)/src/libharfbuzz.la: lib
+$(top_builddir)/src/libharfbuzz-subset.la: libs
 
 EXTRA_DIST += \
        README \
        run-shape-fuzzer-tests.py \
        run-subset-fuzzer-tests.py \
        CMakeLists.txt \
+       fonts \
        $(NULL)
 
 check_PROGRAMS = \
        hb-shape-fuzzer \
        hb-subset-fuzzer \
-       hb-subset-get-codepoints-fuzzer \
        $(NULL)
 
 AM_CPPFLAGS = \
@@ -31,24 +33,15 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/ \
        -I$(top_builddir)/src/ \
        $(NULL)
-LDADD = \
-       $(top_builddir)/src/libharfbuzz-fuzzing.la \
-       $(NULL)
 
 hb_shape_fuzzer_SOURCES = \
        hb-fuzzer.hh \
        hb-shape-fuzzer.cc \
        main.cc \
        $(NULL)
-hb_shape_fuzzer_LDADD = \
-       $(LDADD) \
-       $(NULL)
-hb_shape_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-hb_shape_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
+hb_shape_fuzzer_LDADD = $(top_builddir)/src/libharfbuzz.la
+hb_shape_fuzzer_CPPFLAGS = $(AM_CPPFLAGS)
+hb_shape_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz.la
 
 hb_subset_fuzzer_SOURCES = \
        hb-fuzzer.hh \
@@ -56,32 +49,15 @@ hb_subset_fuzzer_SOURCES = \
        main.cc \
        $(NULL)
 hb_subset_fuzzer_LDADD = \
-       $(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
-       $(NULL)
-hb_subset_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-hb_subset_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
-
-hb_subset_get_codepoints_fuzzer_SOURCES = \
-       hb-fuzzer.hh \
-       hb-subset-get-codepoints-fuzzer.cc \
-       main.cc \
-       $(NULL)
-hb_subset_get_codepoints_fuzzer_LDADD = \
-       $(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
-       $(NULL)
-hb_subset_get_codepoints_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-hb_subset_get_codepoints_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
+       $(top_builddir)/src/libharfbuzz.la \
+       $(top_builddir)/src/libharfbuzz-subset.la
+hb_subset_fuzzer_CPPFLAGS = $(AM_CPPFLAGS)
+hb_subset_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz-subset.la
 
 check:
        EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py
        EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
+check-valgrind:
+       $(AM_V_at)RUN_VALGRIND=1 $(MAKE) $(AM_MAKEFLGS) check
 
 -include $(top_srcdir)/git.mk
index dcbe021..7675ade 100644 (file)
@@ -90,7 +90,7 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 check_PROGRAMS = hb-shape-fuzzer$(EXEEXT) hb-subset-fuzzer$(EXEEXT) \
-       hb-subset-get-codepoints-fuzzer$(EXEEXT) $(am__EXEEXT_1)
+       $(am__EXEEXT_1)
 subdir = test/fuzzing
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
@@ -98,8 +98,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -113,9 +112,6 @@ am_hb_shape_fuzzer_OBJECTS =  \
        hb_shape_fuzzer-hb-shape-fuzzer.$(OBJEXT) \
        hb_shape_fuzzer-main.$(OBJEXT) $(am__objects_1)
 hb_shape_fuzzer_OBJECTS = $(am_hb_shape_fuzzer_OBJECTS)
-am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = $(top_builddir)/src/libharfbuzz-fuzzing.la \
-       $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
@@ -124,11 +120,6 @@ am_hb_subset_fuzzer_OBJECTS =  \
        hb_subset_fuzzer-hb-subset-fuzzer.$(OBJEXT) \
        hb_subset_fuzzer-main.$(OBJEXT) $(am__objects_1)
 hb_subset_fuzzer_OBJECTS = $(am_hb_subset_fuzzer_OBJECTS)
-am_hb_subset_get_codepoints_fuzzer_OBJECTS = hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.$(OBJEXT) \
-       hb_subset_get_codepoints_fuzzer-main.$(OBJEXT) \
-       $(am__objects_1)
-hb_subset_get_codepoints_fuzzer_OBJECTS =  \
-       $(am_hb_subset_get_codepoints_fuzzer_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -181,10 +172,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(hb_shape_fuzzer_SOURCES) $(hb_subset_fuzzer_SOURCES) \
-       $(hb_subset_get_codepoints_fuzzer_SOURCES)
-DIST_SOURCES = $(hb_shape_fuzzer_SOURCES) $(hb_subset_fuzzer_SOURCES) \
-       $(hb_subset_get_codepoints_fuzzer_SOURCES)
+SOURCES = $(hb_shape_fuzzer_SOURCES) $(hb_subset_fuzzer_SOURCES)
+DIST_SOURCES = $(hb_shape_fuzzer_SOURCES) $(hb_subset_fuzzer_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -328,6 +317,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -398,7 +389,7 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 NULL = 
 EXTRA_DIST = README run-shape-fuzzer-tests.py \
-       run-subset-fuzzer-tests.py CMakeLists.txt $(NULL)
+       run-subset-fuzzer-tests.py CMakeLists.txt fonts $(NULL)
 CLEANFILES = 
 DISTCLEANFILES = 
 MAINTAINERCLEANFILES = 
@@ -408,28 +399,15 @@ AM_CPPFLAGS = \
        -I$(top_builddir)/src/ \
        $(NULL)
 
-LDADD = \
-       $(top_builddir)/src/libharfbuzz-fuzzing.la \
-       $(NULL)
-
 hb_shape_fuzzer_SOURCES = \
        hb-fuzzer.hh \
        hb-shape-fuzzer.cc \
        main.cc \
        $(NULL)
 
-hb_shape_fuzzer_LDADD = \
-       $(LDADD) \
-       $(NULL)
-
-hb_shape_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-
-hb_shape_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
-
+hb_shape_fuzzer_LDADD = $(top_builddir)/src/libharfbuzz.la
+hb_shape_fuzzer_CPPFLAGS = $(AM_CPPFLAGS)
+hb_shape_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz.la
 hb_subset_fuzzer_SOURCES = \
        hb-fuzzer.hh \
        hb-subset-fuzzer.cc \
@@ -437,35 +415,11 @@ hb_subset_fuzzer_SOURCES = \
        $(NULL)
 
 hb_subset_fuzzer_LDADD = \
-       $(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
-       $(NULL)
-
-hb_subset_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-
-hb_subset_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
-
-hb_subset_get_codepoints_fuzzer_SOURCES = \
-       hb-fuzzer.hh \
-       hb-subset-get-codepoints-fuzzer.cc \
-       main.cc \
-       $(NULL)
-
-hb_subset_get_codepoints_fuzzer_LDADD = \
-       $(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
-       $(NULL)
-
-hb_subset_get_codepoints_fuzzer_CPPFLAGS = \
-       $(AM_CPPFLAGS) \
-       $(NULL)
-
-hb_subset_get_codepoints_fuzzer_DEPENDENCIES = \
-       lib \
-       $(NULL)
+       $(top_builddir)/src/libharfbuzz.la \
+       $(top_builddir)/src/libharfbuzz-subset.la
 
+hb_subset_fuzzer_CPPFLAGS = $(AM_CPPFLAGS)
+hb_subset_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz-subset.la
 all: all-am
 
 .SUFFIXES:
@@ -517,10 +471,6 @@ hb-subset-fuzzer$(EXEEXT): $(hb_subset_fuzzer_OBJECTS) $(hb_subset_fuzzer_DEPEND
        @rm -f hb-subset-fuzzer$(EXEEXT)
        $(AM_V_CXXLD)$(CXXLINK) $(hb_subset_fuzzer_OBJECTS) $(hb_subset_fuzzer_LDADD) $(LIBS)
 
-hb-subset-get-codepoints-fuzzer$(EXEEXT): $(hb_subset_get_codepoints_fuzzer_OBJECTS) $(hb_subset_get_codepoints_fuzzer_DEPENDENCIES) $(EXTRA_hb_subset_get_codepoints_fuzzer_DEPENDENCIES) 
-       @rm -f hb-subset-get-codepoints-fuzzer$(EXEEXT)
-       $(AM_V_CXXLD)$(CXXLINK) $(hb_subset_get_codepoints_fuzzer_OBJECTS) $(hb_subset_get_codepoints_fuzzer_LDADD) $(LIBS)
-
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
 
@@ -531,8 +481,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb_shape_fuzzer-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb_subset_fuzzer-hb-subset-fuzzer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb_subset_fuzzer-main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Po@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -611,34 +559,6 @@ hb_subset_fuzzer-main.obj: main.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hb_subset_fuzzer-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi`
 
-hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.o: hb-subset-get-codepoints-fuzzer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.o -MD -MP -MF $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Tpo -c -o hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.o `test -f 'hb-subset-get-codepoints-fuzzer.cc' || echo '$(srcdir)/'`hb-subset-get-codepoints-fuzzer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Tpo $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-get-codepoints-fuzzer.cc' object='hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.o `test -f 'hb-subset-get-codepoints-fuzzer.cc' || echo '$(srcdir)/'`hb-subset-get-codepoints-fuzzer.cc
-
-hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.obj: hb-subset-get-codepoints-fuzzer.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.obj -MD -MP -MF $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Tpo -c -o hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.obj `if test -f 'hb-subset-get-codepoints-fuzzer.cc'; then $(CYGPATH_W) 'hb-subset-get-codepoints-fuzzer.cc'; else $(CYGPATH_W) '$(srcdir)/hb-subset-get-codepoints-fuzzer.cc'; fi`
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Tpo $(DEPDIR)/hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='hb-subset-get-codepoints-fuzzer.cc' object='hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hb_subset_get_codepoints_fuzzer-hb-subset-get-codepoints-fuzzer.obj `if test -f 'hb-subset-get-codepoints-fuzzer.cc'; then $(CYGPATH_W) 'hb-subset-get-codepoints-fuzzer.cc'; else $(CYGPATH_W) '$(srcdir)/hb-subset-get-codepoints-fuzzer.cc'; fi`
-
-hb_subset_get_codepoints_fuzzer-main.o: main.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT hb_subset_get_codepoints_fuzzer-main.o -MD -MP -MF $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Tpo -c -o hb_subset_get_codepoints_fuzzer-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Tpo $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='main.cc' object='hb_subset_get_codepoints_fuzzer-main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hb_subset_get_codepoints_fuzzer-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc
-
-hb_subset_get_codepoints_fuzzer-main.obj: main.cc
-@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT hb_subset_get_codepoints_fuzzer-main.obj -MD -MP -MF $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Tpo -c -o hb_subset_get_codepoints_fuzzer-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi`
-@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Tpo $(DEPDIR)/hb_subset_get_codepoints_fuzzer-main.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='main.cc' object='hb_subset_get_codepoints_fuzzer-main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hb_subset_get_codepoints_fuzzer_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o hb_subset_get_codepoints_fuzzer-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi`
-
 mostlyclean-libtool:
        -rm -f *.lo
 
@@ -857,14 +777,18 @@ uninstall-am:
 
 # Convenience targets:
 lib:
-       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src fuzzing
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
-$(top_builddir)/src/libharfbuzz-fuzzing.la: lib
-$(top_builddir)/src/libharfbuzz-subset-fuzzing.la: lib
+$(top_builddir)/src/libharfbuzz.la: lib
+$(top_builddir)/src/libharfbuzz-subset.la: libs
 
 check:
        EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py
        EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
+check-valgrind:
+       $(AM_V_at)RUN_VALGRIND=1 $(MAKE) $(AM_MAKEFLGS) check
 
 -include $(top_srcdir)/git.mk
 
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-5517117891805184 b/test/fuzzing/fonts/clusterfuzz-testcase-5517117891805184
new file mode 100644 (file)
index 0000000..0c7b518
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-5517117891805184 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-6107935408390144 b/test/fuzzing/fonts/clusterfuzz-testcase-6107935408390144
new file mode 100644 (file)
index 0000000..4c81a86
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-6107935408390144 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-5662671558934528 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-5662671558934528
new file mode 100644 (file)
index 0000000..cbb81ac
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-5662671558934528 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6243458541944832 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6243458541944832
new file mode 100644 (file)
index 0000000..64864aa
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6243458541944832 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6696647723581440 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6696647723581440
new file mode 100644 (file)
index 0000000..8b1c293
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-fuzzer-6696647723581440 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5097734906839040 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5097734906839040
new file mode 100644 (file)
index 0000000..8b45452
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5097734906839040 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5634395566768128 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5634395566768128
new file mode 100644 (file)
index 0000000..cd1a293
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5634395566768128 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5688420752424960 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5688420752424960
new file mode 100644 (file)
index 0000000..1fe962b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5688420752424960 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5728971283496960 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5728971283496960
new file mode 100644 (file)
index 0000000..25d7bf1
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5728971283496960 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5746142327865344 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5746142327865344
new file mode 100644 (file)
index 0000000..1c1607b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5746142327865344 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5750379279548416 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5750379279548416
new file mode 100644 (file)
index 0000000..f014d4b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-shape-fuzzer-5750379279548416 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5643036478930944 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5643036478930944
new file mode 100644 (file)
index 0000000..9a52336
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5643036478930944 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5686186874503168 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5686186874503168
new file mode 100644 (file)
index 0000000..86f4ad7
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5686186874503168 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5762137968869376 b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5762137968869376
new file mode 100644 (file)
index 0000000..dca0b7d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-hb-subset-fuzzer-5762137968869376 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-4884742786777088 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-4884742786777088
new file mode 100644 (file)
index 0000000..ac7da9f
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-4884742786777088 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5255344882188288 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5255344882188288
new file mode 100644 (file)
index 0000000..ab1aede
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5255344882188288 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5924299061854208 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5924299061854208
new file mode 100644 (file)
index 0000000..a8ea332
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-5924299061854208 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-6460279560863744 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-6460279560863744
new file mode 100644 (file)
index 0000000..1cbe75a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-6460279560863744 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5126525414014976 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5126525414014976
new file mode 100644 (file)
index 0000000..74cc027
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5126525414014976 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5166320261529600 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5166320261529600
new file mode 100644 (file)
index 0000000..b79765a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5166320261529600 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5659690013556736 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5659690013556736
new file mode 100644 (file)
index 0000000..9293c46
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5659690013556736 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5662548265009152 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5662548265009152
new file mode 100644 (file)
index 0000000..0b68a30
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5662548265009152 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5973566991106048 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5973566991106048
new file mode 100644 (file)
index 0000000..984bb4b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5973566991106048 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4523479581851648 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4523479581851648
new file mode 100644 (file)
index 0000000..1d16d70
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4523479581851648 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4548492505645056 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4548492505645056
new file mode 100644 (file)
index 0000000..065080f
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4548492505645056 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4687441845813248 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4687441845813248
new file mode 100644 (file)
index 0000000..d3e9f46
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4687441845813248 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4706238090706944 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4706238090706944
new file mode 100644 (file)
index 0000000..269813a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4706238090706944 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4769173588672512 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4769173588672512
new file mode 100644 (file)
index 0000000..5426914
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4769173588672512 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4827735151083520 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4827735151083520
new file mode 100644 (file)
index 0000000..f5f1255
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4827735151083520 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4841745322868736 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4841745322868736
new file mode 100644 (file)
index 0000000..5e0f74d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4841745322868736 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4884742786777088 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4884742786777088
new file mode 100644 (file)
index 0000000..ac7da9f
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-4884742786777088 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5216838347653120 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5216838347653120
new file mode 100644 (file)
index 0000000..23cc590
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5216838347653120 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5255344882188288 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5255344882188288
new file mode 100644 (file)
index 0000000..ab1aede
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5255344882188288 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5294584596791296 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5294584596791296
new file mode 100644 (file)
index 0000000..bc16579
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5294584596791296 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5303930168803328 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5303930168803328
new file mode 100644 (file)
index 0000000..805fe4d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5303930168803328 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5388906574905344 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5388906574905344
new file mode 100644 (file)
index 0000000..5f7ff7c
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5388906574905344 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5517117891805184 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5517117891805184
new file mode 100644 (file)
index 0000000..0c7b518
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5517117891805184 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5617496443846656 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5617496443846656
new file mode 100644 (file)
index 0000000..aeffab5
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5617496443846656 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5672141338968064 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5672141338968064
new file mode 100644 (file)
index 0000000..3c8303f
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5672141338968064 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5700697074958336 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5700697074958336
new file mode 100644 (file)
index 0000000..2664e30
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5700697074958336 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5713868010553344 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5713868010553344
new file mode 100644 (file)
index 0000000..ee0a721
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5713868010553344 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5720051798769664 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5720051798769664
new file mode 100644 (file)
index 0000000..999f296
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5720051798769664 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5924299061854208 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5924299061854208
new file mode 100644 (file)
index 0000000..a8ea332
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-5924299061854208 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6023178755244032 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6023178755244032
new file mode 100644 (file)
index 0000000..b0da152
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6023178755244032 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6111685556305920 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6111685556305920
new file mode 100644 (file)
index 0000000..8c1940d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6111685556305920 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6210176798425088 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6210176798425088
new file mode 100644 (file)
index 0000000..1c62961
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6210176798425088 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6260579246276608 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6260579246276608
new file mode 100644 (file)
index 0000000..036a206
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6260579246276608 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6264625609834496 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6264625609834496
new file mode 100644 (file)
index 0000000..035dd72
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6264625609834496 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6278851874258944 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6278851874258944
new file mode 100644 (file)
index 0000000..775c918
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6278851874258944 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6424351550210048 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6424351550210048
new file mode 100644 (file)
index 0000000..afb08c5
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6424351550210048 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6460279560863744 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6460279560863744
new file mode 100644 (file)
index 0000000..1cbe75a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6460279560863744 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6576177596596224 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6576177596596224
new file mode 100644 (file)
index 0000000..35171ee
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6576177596596224 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6595199411159040 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6595199411159040
new file mode 100644 (file)
index 0000000..a4d503d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6595199411159040 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6624904746106880 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6624904746106880
new file mode 100644 (file)
index 0000000..fcc1b64
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6624904746106880 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6723367514144768 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6723367514144768
new file mode 100644 (file)
index 0000000..55b1ef8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-fuzzer-6723367514144768 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5175735354916864 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5175735354916864
new file mode 100644 (file)
index 0000000..72fdfc6
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5175735354916864 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5629524117553152 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5629524117553152
new file mode 100644 (file)
index 0000000..01ca517
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5629524117553152 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5630246225707008 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5630246225707008
new file mode 100644 (file)
index 0000000..ab534e3
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5630246225707008 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5631444412530688 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5631444412530688
new file mode 100644 (file)
index 0000000..25f7d69
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5631444412530688 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5633985665826816 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5633985665826816
new file mode 100644 (file)
index 0000000..387d7fd
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5633985665826816 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634443633491968 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634443633491968
new file mode 100644 (file)
index 0000000..c63bcc5
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634443633491968 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634620935110656 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634620935110656
new file mode 100644 (file)
index 0000000..39f9c3c
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5634620935110656 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5635082459545600 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5635082459545600
new file mode 100644 (file)
index 0000000..6d0feff
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5635082459545600 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5647267827023872 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5647267827023872
new file mode 100644 (file)
index 0000000..068e7e8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5647267827023872 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5649959857160192 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5649959857160192
new file mode 100644 (file)
index 0000000..72e702e
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5649959857160192 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5650286710882304 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5650286710882304
new file mode 100644 (file)
index 0000000..95322e1
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5650286710882304 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5652019562414080 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5652019562414080
new file mode 100644 (file)
index 0000000..8e85980
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5652019562414080 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5656511058018304 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5656511058018304
new file mode 100644 (file)
index 0000000..bb68572
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5656511058018304 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5659641787187200 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5659641787187200
new file mode 100644 (file)
index 0000000..8a63dc4
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5659641787187200 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5664873493561344 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5664873493561344
new file mode 100644 (file)
index 0000000..dfc36d8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5664873493561344 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5667182741028864 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5667182741028864
new file mode 100644 (file)
index 0000000..0c40dd8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5667182741028864 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5668791174823936 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5668791174823936
new file mode 100644 (file)
index 0000000..1f750c1
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5668791174823936 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5672261407735808 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5672261407735808
new file mode 100644 (file)
index 0000000..6297549
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5672261407735808 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5674361600606208 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5674361600606208
new file mode 100644 (file)
index 0000000..1d4f84a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5674361600606208 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5677421274071040 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5677421274071040
new file mode 100644 (file)
index 0000000..3be3b91
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5677421274071040 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5679244475105280 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5679244475105280
new file mode 100644 (file)
index 0000000..2894bdc
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5679244475105280 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5685596677210112 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5685596677210112
new file mode 100644 (file)
index 0000000..d9937a3
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5685596677210112 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5686369209286656 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5686369209286656
new file mode 100644 (file)
index 0000000..9f47ca8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5686369209286656 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5688420752424960 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5688420752424960
new file mode 100644 (file)
index 0000000..e9f01a2
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5688420752424960 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152
new file mode 100644 (file)
index 0000000..6c73900
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5695615258853376 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5695615258853376
new file mode 100644 (file)
index 0000000..af43a44
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5695615258853376 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5696686572175360 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5696686572175360
new file mode 100644 (file)
index 0000000..c6e8bfd
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5696686572175360 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5700264032468992 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5700264032468992
new file mode 100644 (file)
index 0000000..82a462b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5700264032468992 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5706010589659136 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5706010589659136
new file mode 100644 (file)
index 0000000..7e15f4b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5706010589659136 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5716208469409792 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5716208469409792
new file mode 100644 (file)
index 0000000..00915d6
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5716208469409792 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718464350650368 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718464350650368
new file mode 100644 (file)
index 0000000..d511e9d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718464350650368 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718889451749376 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718889451749376
new file mode 100644 (file)
index 0000000..6360579
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5718889451749376 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5719982789361664 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5719982789361664
new file mode 100644 (file)
index 0000000..0515086
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5719982789361664 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5722888989048832 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5722888989048832
new file mode 100644 (file)
index 0000000..df1556b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5722888989048832 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725129603022848 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725129603022848
new file mode 100644 (file)
index 0000000..8ba0f9d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725129603022848 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725855502827520 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725855502827520
new file mode 100644 (file)
index 0000000..5781bba
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5725855502827520 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5726089628876800 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5726089628876800
new file mode 100644 (file)
index 0000000..61750d4
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5726089628876800 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5729361857085440 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5729361857085440
new file mode 100644 (file)
index 0000000..a6ecc61
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5729361857085440 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5733166795456512 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5733166795456512
new file mode 100644 (file)
index 0000000..dfaf6d9
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5733166795456512 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5734736291430400 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5734736291430400
new file mode 100644 (file)
index 0000000..31c805c
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5734736291430400 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536
new file mode 100644 (file)
index 0000000..ff6ef6e
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5735679418433536 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5736657639178240 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5736657639178240
new file mode 100644 (file)
index 0000000..343429c
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5736657639178240 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5738888765636608 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5738888765636608
new file mode 100644 (file)
index 0000000..28e72df
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5738888765636608 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5740171484463104 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5740171484463104
new file mode 100644 (file)
index 0000000..aef0d92
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5740171484463104 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5750379279548416 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5750379279548416
new file mode 100644 (file)
index 0000000..b4551bf
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5750379279548416 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568
new file mode 100644 (file)
index 0000000..03f240f
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762490181353472 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762490181353472
new file mode 100644 (file)
index 0000000..db06a1c
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762490181353472 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762953198960640 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762953198960640
new file mode 100644 (file)
index 0000000..9d64eaf
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5762953198960640 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5764636557705216 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5764636557705216
new file mode 100644 (file)
index 0000000..b07416b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5764636557705216 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768046065483776 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768046065483776
new file mode 100644 (file)
index 0000000..0ab1447
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768046065483776 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768601332613120 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768601332613120
new file mode 100644 (file)
index 0000000..385e670
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5768601332613120 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5067936541179904 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5067936541179904
new file mode 100644 (file)
index 0000000..9f57f7b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5067936541179904 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5359635656605696 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5359635656605696
new file mode 100644 (file)
index 0000000..8a659c6
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5359635656605696 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872
new file mode 100644 (file)
index 0000000..6307ddd
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5542653037903872 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5629878397829120 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5629878397829120
new file mode 100644 (file)
index 0000000..a055cdb
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5629878397829120 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5651059347816448 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5651059347816448
new file mode 100644 (file)
index 0000000..b2e4034
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5651059347816448 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5660711141769216 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5660711141769216
new file mode 100644 (file)
index 0000000..302a1c4
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5660711141769216 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5669437462544384 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5669437462544384
new file mode 100644 (file)
index 0000000..c4eb909
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5669437462544384 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480
new file mode 100644 (file)
index 0000000..49bcb30
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5670861909524480 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672006905757696 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672006905757696
new file mode 100644 (file)
index 0000000..cb5fb83
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672006905757696 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672913680728064 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672913680728064
new file mode 100644 (file)
index 0000000..fdb5bff
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5672913680728064 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5690658895953920 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5690658895953920
new file mode 100644 (file)
index 0000000..abafa4b
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5690658895953920 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5695279609675776 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5695279609675776
new file mode 100644 (file)
index 0000000..f016262
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5695279609675776 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696607199166464 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696607199166464
new file mode 100644 (file)
index 0000000..ca4fcd7
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696607199166464 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5710107829075968 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5710107829075968
new file mode 100644 (file)
index 0000000..5fef2f8
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5710107829075968 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5711951464759296 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5711951464759296
new file mode 100644 (file)
index 0000000..b20e849
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5711951464759296 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5718215406125056 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5718215406125056
new file mode 100644 (file)
index 0000000..a6d87da
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5718215406125056 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5725847365877760 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5725847365877760
new file mode 100644 (file)
index 0000000..3764bed
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5725847365877760 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5743250149736448 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5743250149736448
new file mode 100644 (file)
index 0000000..b17c949
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5743250149736448 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5747265633779712 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5747265633779712
new file mode 100644 (file)
index 0000000..463e0c1
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5747265633779712 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560
new file mode 100644 (file)
index 0000000..d622c25
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816
new file mode 100644 (file)
index 0000000..7f41718
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750420593442816 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5758598970343424 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5758598970343424
new file mode 100644 (file)
index 0000000..7087f63
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5758598970343424 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5765071062958080 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5765071062958080
new file mode 100644 (file)
index 0000000..1f9be04
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5765071062958080 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5768186323009536 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5768186323009536
new file mode 100644 (file)
index 0000000..858604d
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5768186323009536 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6543700493598720 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6543700493598720
new file mode 100644 (file)
index 0000000..c0e9811
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6543700493598720 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5203067375976448 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5203067375976448
new file mode 100644 (file)
index 0000000..cf92d88
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5203067375976448 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5630904853069824 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5630904853069824
new file mode 100644 (file)
index 0000000..7c242ee
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5630904853069824 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5687638085337088 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5687638085337088
new file mode 100644 (file)
index 0000000..e8706f3
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5687638085337088 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5736539338833920 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5736539338833920
new file mode 100644 (file)
index 0000000..f572621
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5736539338833920 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5930139383758848 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5930139383758848
new file mode 100644 (file)
index 0000000..940fbd5
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5930139383758848 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648
new file mode 100644 (file)
index 0000000..b506d2a
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-5973295416475648 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912
new file mode 100644 (file)
index 0000000..ffcea64
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6136125075750912 differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6394290358976512 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6394290358976512
new file mode 100644 (file)
index 0000000..8ee7752
Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-get-codepoints-fuzzer-6394290358976512 differ
index 79f3222..5723db9 100644 (file)
@@ -3,50 +3,45 @@
 #include <hb-ot.h>
 #include <string.h>
 
+#define TEST_OT_FACE_NO_MAIN 1
+#include "../api/test-ot-face.c"
+#undef TEST_OT_FACE_NO_MAIN
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-  hb_blob_t *blob = hb_blob_create((const char *)data, size,
-                                   HB_MEMORY_MODE_READONLY, NULL, NULL);
-  hb_face_t *face = hb_face_create(blob, 0);
-  hb_font_t *font = hb_font_create(face);
-  hb_ot_font_set_funcs(font);
-  hb_font_set_scale(font, 12, 12);
+  hb_blob_t *blob = hb_blob_create ((const char *)data, size,
+                                   HB_MEMORY_MODE_READONLY, NULL, NULL);
+  hb_face_t *face = hb_face_create (blob, 0);
+  hb_font_t *font = hb_font_create (face);
+  hb_ot_font_set_funcs (font);
+  hb_font_set_scale (font, 12, 12);
 
   {
     const char text[] = "ABCDEXYZ123@_%&)*$!";
-    hb_buffer_t *buffer = hb_buffer_create();
-    hb_buffer_add_utf8(buffer, text, -1, 0, -1);
-    hb_buffer_guess_segment_properties(buffer);
-    hb_shape(font, buffer, NULL, 0);
-    hb_buffer_destroy(buffer);
+    hb_buffer_t *buffer = hb_buffer_create ();
+    hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
+    hb_buffer_guess_segment_properties (buffer);
+    hb_shape (font, buffer, NULL, 0);
+    hb_buffer_destroy (buffer);
   }
 
-  uint32_t text32[16];
-  if (size > sizeof(text32)) {
-    memcpy(text32, data + size - sizeof(text32), sizeof(text32));
-    hb_buffer_t *buffer = hb_buffer_create();
-    hb_buffer_add_utf32(buffer, text32, sizeof(text32)/sizeof(text32[0]), 0, -1);
-    hb_buffer_guess_segment_properties(buffer);
-    hb_shape(font, buffer, NULL, 0);
-
-    unsigned int len = hb_buffer_get_length (buffer);
-    hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL);
-    //hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, NULL);
-    for (unsigned int i = 0; i < len; i++)
-    {
-      hb_glyph_info_t info = infos[i];
-      //hb_glyph_position_t pos = positions[i];
-
-      hb_glyph_extents_t extents;
-      hb_font_get_glyph_extents (font, info.codepoint, &extents);
-    }
-
-    hb_buffer_destroy(buffer);
-  }
+  uint32_t text32[16] = {0};
+  unsigned int len = sizeof (text32);
+  if (size < len)
+    len = size;
+  memcpy(text32, data + size - len, len);
+
+  hb_buffer_t *buffer = hb_buffer_create ();
+  hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1);
+  hb_buffer_guess_segment_properties (buffer);
+  hb_shape (font, buffer, NULL, 0);
+  hb_buffer_destroy (buffer);
 
+  /* Misc calls on face. */
+  test_face (face, text32[15]);
 
-  hb_font_destroy(font);
-  hb_face_destroy(face);
-  hb_blob_destroy(blob);
+  hb_font_destroy (font);
+  hb_face_destroy (face);
+  hb_blob_destroy (blob);
   return 0;
 }
index 28ce921..3a71f22 100644 (file)
@@ -6,17 +6,16 @@
 
 #include "hb-subset.h"
 
-void trySubset (hb_face_t *face,
-                const hb_codepoint_t text[],
-                int text_length,
-                bool drop_hints,
-                bool drop_ot_layout)
+static void
+trySubset (hb_face_t *face,
+          const hb_codepoint_t text[],
+          int text_length,
+          bool drop_hints,
+          bool drop_layout)
 {
-  hb_subset_profile_t *profile = hb_subset_profile_create ();
-
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
-  *hb_subset_input_drop_hints (input) = drop_hints;
-  *hb_subset_input_drop_ot_layout (input) = drop_ot_layout;
+  hb_subset_input_set_drop_hints (input, drop_hints);
+  hb_subset_input_set_drop_layout (input, drop_layout);
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
 
   for (int i = 0; i < text_length; i++)
@@ -24,23 +23,23 @@ void trySubset (hb_face_t *face,
     hb_set_add (codepoints, text[i]);
   }
 
-  hb_face_t *result = hb_subset (face, profile, input);
+  hb_face_t *result = hb_subset (face, input);
   hb_face_destroy (result);
 
   hb_subset_input_destroy (input);
-  hb_subset_profile_destroy (profile);
 }
 
-void trySubset (hb_face_t *face,
-                const hb_codepoint_t text[],
-                int text_length)
+static void
+trySubset (hb_face_t *face,
+          const hb_codepoint_t text[],
+          int text_length)
 {
   for (unsigned int drop_hints = 0; drop_hints < 2; drop_hints++)
   {
-    for (unsigned int drop_ot_layout = 0; drop_ot_layout < 2; drop_ot_layout++)
+    for (unsigned int drop_layout = 0; drop_layout < 2; drop_layout++)
     {
       trySubset (face, text, text_length,
-                 (bool) drop_hints, (bool) drop_ot_layout);
+                (bool) drop_hints, (bool) drop_layout);
     }
   }
 }
@@ -48,22 +47,27 @@ void trySubset (hb_face_t *face,
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
-                                    HB_MEMORY_MODE_READONLY, NULL, NULL);
+                                   HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create (blob, 0);
 
+  /* Just test this API here quickly. */
+  hb_set_t *output = hb_set_create();
+  hb_face_collect_unicodes (face, output);
+  hb_set_destroy (output);
+
   const hb_codepoint_t text[] =
       {
-        'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
-        '3', '@', '_', '%', '&', ')', '*', '$', '!'
+       'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
+       '3', '@', '_', '%', '&', ')', '*', '$', '!'
       };
 
   trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t));
 
   hb_codepoint_t text_from_data[16];
   if (size > sizeof(text_from_data)) {
-    memcpy(text_from_data,
-           data + size - sizeof(text_from_data),
-           sizeof(text_from_data));
+    memcpy (text_from_data,
+           data + size - sizeof(text_from_data),
+           sizeof(text_from_data));
     unsigned int text_size = sizeof (text_from_data) / sizeof (hb_codepoint_t);
     trySubset (face, text_from_data, text_size);
   }
diff --git a/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc b/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
deleted file mode 100644 (file)
index 38f338b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "hb-fuzzer.hh"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "hb-subset.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
-  hb_blob_t *blob = hb_blob_create ((const char *)data, size,
-                                    HB_MEMORY_MODE_READONLY, NULL, NULL);
-  hb_face_t *face = hb_face_create (blob, 0);
-
-  hb_set_t *output = hb_set_create();
-  hb_subset_get_all_codepoints (face, output);
-
-  hb_set_destroy (output);
-  hb_face_destroy (face);
-  hb_blob_destroy (blob);
-
-  return 0;
-}
index 4692f7b..f15247c 100644 (file)
@@ -1,21 +1,23 @@
 #include "hb-fuzzer.hh"
 
-#include <iostream>
-#include <iterator>
-#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
 #include <assert.h>
 
-std::string FileToString(const std::string &Path) {
-  /* TODO This silently passes if file does not exist.  Fix it! */
-  std::ifstream T(Path.c_str());
-  return std::string((std::istreambuf_iterator<char>(T)),
-                     std::istreambuf_iterator<char>());
-}
-
 int main(int argc, char **argv) {
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+  unsigned int len;
+  const char *font_data = hb_blob_get_data (blob, &len);
+  if (len == 0)
+  {
+    printf ("Font not found.\n");
+    exit (1);
+  }
+
   for (int i = 1; i < argc; i++) {
-    std::string s = FileToString(argv[i]);
-    std::cout << argv[i] << std::endl;
-    LLVMFuzzerTestOneInput((const unsigned char*)s.data(), s.size());
+    printf ("%s\n", argv[i]);
+    LLVMFuzzerTestOneInput((const uint8_t *) font_data, len);
   }
+
+  hb_blob_destroy (blob);
 }
index fea0b01..e3d180f 100755 (executable)
@@ -2,7 +2,54 @@
 
 from __future__ import print_function, division, absolute_import
 
-import sys, os, subprocess
+import sys, os, subprocess, tempfile, threading
+
+
+def which(program):
+       # https://stackoverflow.com/a/377028
+       def is_exe(fpath):
+               return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+       fpath, _ = os.path.split(program)
+       if fpath:
+               if is_exe(program):
+                       return program
+       else:
+               for path in os.environ["PATH"].split(os.pathsep):
+                       exe_file = os.path.join(path, program)
+                       if is_exe(exe_file):
+                               return exe_file
+
+       return None
+
+
+def cmd(command):
+       # https://stackoverflow.com/a/4408409
+       # https://stackoverflow.com/a/10012262
+       with tempfile.TemporaryFile() as tempf:
+               p = subprocess.Popen (command, stderr=tempf)
+               is_killed = {'value': False}
+
+               def timeout(p, is_killed):
+                       is_killed['value'] = True
+                       p.kill()
+               timer = threading.Timer (2, timeout, [p, is_killed])
+
+               try:
+                       timer.start()
+                       p.wait ()
+                       tempf.seek (0)
+                       text = tempf.read().decode ("utf-8").strip ()
+                       returncode = p.returncode
+               finally:
+                       timer.cancel()
+
+               if is_killed['value']:
+                       text = 'error: timeout, ' + text
+                       returncode = 1
+
+               return text, returncode
+
 
 srcdir = os.environ.get ("srcdir", ".")
 EXEEXT = os.environ.get ("EXEEXT", "")
@@ -20,14 +67,31 @@ please provide it as the first argument to the tool""")
 print ('hb_shape_fuzzer:', hb_shape_fuzzer)
 fails = 0
 
-parent_path = os.path.join (srcdir, "..", "shaping", "data", "in-house", "tests")
-for line in open (os.path.join (parent_path, "fuzzed.tests")):
-       font = line.split (":")[0]
-       font_path = os.path.join (parent_path, font)
+valgrind = None
+if os.environ.get('RUN_VALGRIND', ''):
+       valgrind = which ('valgrind')
+
+parent_path = os.path.join (srcdir, "fonts")
+for file in os.listdir (parent_path):
+       path = os.path.join(parent_path, file)
+
+       text, returncode = cmd ([hb_shape_fuzzer, path])
+       if text.strip ():
+               print (text)
+
+       failed = False
+       if returncode != 0 or 'error' in text:
+               print ('failure on %s' % file)
+               failed = True
 
-       p = subprocess.Popen ([hb_shape_fuzzer, font_path])
+       if valgrind:
+               text, returncode = cmd ([valgrind, '--error-exitcode=1', hb_shape_fuzzer, path])
+               if returncode:
+                       print (text)
+                       print ('failure on %s' % file)
+                       failed = True
 
-       if p.wait () != 0:
+       if failed:
                fails = fails + 1
 
 if fails:
index 0136288..7392a92 100755 (executable)
@@ -8,7 +8,6 @@ srcdir = os.environ.get ("srcdir", ".")
 EXEEXT = os.environ.get ("EXEEXT", "")
 top_builddir = os.environ.get ("top_builddir", ".")
 hb_subset_fuzzer = os.path.join (top_builddir, "hb-subset-fuzzer" + EXEEXT)
-hb_subset_get_codepoints_fuzzer = os.path.join (top_builddir, "hb-subset-get-codepoints-fuzzer" + EXEEXT)
 
 if not os.path.exists (hb_subset_fuzzer):
         if len (sys.argv) < 2 or not os.path.exists (sys.argv[1]):
@@ -18,35 +17,28 @@ please provide it as the first argument to the tool""")
 
         hb_subset_fuzzer = sys.argv[1]
 
-if not os.path.exists (hb_subset_get_codepoints_fuzzer):
-        if len (sys.argv) < 3 or not os.path.exists (sys.argv[2]):
-                print ("""Failed to find hb-subset-get-codepoints-fuzzer binary automatically,
-please provide it as the second argument to the tool""")
-                sys.exit (1)
-
-        hb_subset_get_codepoints_fuzzer = sys.argv[2]
-
 print ('hb_subset_fuzzer:', hb_subset_fuzzer)
 fails = 0
 
-parent_path = os.path.join (srcdir, "..", "subset", "data", "fonts")
-print ("running subset fuzzer against fonts in %s" % parent_path)
-for file in os.listdir (parent_path):
-        path = os.path.join(parent_path, file)
+def run_dir (parent_path):
+       global fails
+       for file in os.listdir (parent_path):
+               path = os.path.join(parent_path, file)
 
-        print ("running subset fuzzer against %s" % path)
-        p = subprocess.Popen ([hb_subset_fuzzer, path])
+               print ("running subset fuzzer against %s" % path)
+               p = subprocess.Popen ([hb_subset_fuzzer, path])
 
-        if p.wait () != 0:
-                print ("failed for %s" % path)
-                fails = fails + 1
+               if p.wait () != 0:
+                       print ("failed for %s" % path)
+                       fails = fails + 1
 
-        print ("running subset get codepoints fuzzer against %s" % path)
-        p = subprocess.Popen ([hb_subset_get_codepoints_fuzzer, path])
+               if p.wait () != 0:
+                       print ("failed for %s" % path)
+                       fails = fails + 1
 
-        if p.wait () != 0:
-                print ("failed for %s" % path)
-                fails = fails + 1
+run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts"))
+# TODO running these tests very slow tests.  Fix and re-enable
+#run_dir (os.path.join (srcdir, "fonts"))
 
 if fails:
         print ("%i subset fuzzer related tests failed." % fails)
index 7c2c999..8e33ede 100644 (file)
@@ -5,6 +5,16 @@ if (HB_BUILD_UTILS)
     add_test (NAME ${test}
       COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/in-house/${test}"
       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
+  endforeach ()
+
+  file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/aots/Makefile.sources" INHOUSE)
+  extract_make_variable (TESTS ${INHOUSE})
+  foreach (test IN ITEMS ${TESTS})
+    add_test (NAME ${test}
+      COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/aots/${test}"
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
   endforeach ()
 
   file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/text-rendering-tests/Makefile.sources" TEXTRENDERING)
@@ -13,5 +23,6 @@ if (HB_BUILD_UTILS)
     add_test (NAME ${test}
       COMMAND "${PYTHON_EXECUTABLE}" run-tests.py $<TARGET_FILE:hb-shape> "data/text-rendering-tests/${test}"
       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+    set_property (TEST ${test} PROPERTY SKIP_RETURN_CODE 77)
   endforeach ()
 endif ()
index 7320336..66272da 100644 (file)
@@ -3,11 +3,15 @@
 NULL =
 EXTRA_DIST =
 CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
 SUBDIRS = data
 
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 EXTRA_DIST += \
        README.md \
index 0ddfa3c..202db22 100644 (file)
@@ -96,8 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -304,6 +303,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -380,6 +381,8 @@ EXTRA_DIST = README.md CMakeLists.txt hb-diff hb-diff-colorize \
        hb-unicode-encode hb-unicode-prettyname record-test.sh \
        run-tests.py texts/in-house $(NULL) hb_test_tools.py $(NULL)
 CLEANFILES = hb_test_tools.py[co] $(NULL)
+DISTCLEANFILES = 
+MAINTAINERCLEANFILES = 
 SUBDIRS = data
 all: all-recursive
 
@@ -606,10 +609,12 @@ clean-generic:
 distclean-generic:
        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
        -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
 
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
 clean: clean-recursive
 
 clean-am: clean-generic clean-libtool mostlyclean-am
@@ -697,6 +702,8 @@ uninstall-am:
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 -include $(top_srcdir)/git.mk
 
index 99498e6..f386fb9 100644 (file)
@@ -25,10 +25,10 @@ what this does is:
   * If the outputs differ, recording fails.  Otherwise, it will move the
     subset font file into `data/in-house/fonts` and name it after its
     hash, and print out the test case input, which you can then redirect
-    to an existing or new test file in `data/in-house/tests` using `-o=`,
+    to an existing or new test file in `data/in-house/tests` using `-o`,
     e.g.:
 ```sh
-$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh -o=data/in-house/tests/test-name.test ../../util/hb-shape font.ttf
+$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh -o data/in-house/tests/test-name.test ../../util/hb-shape font.ttf
 ```
 
 If you created a new test file, add it to `data/in-house/Makefile.sources`
index 4f2c113..01f6c5a 100644 (file)
@@ -4,6 +4,7 @@ NULL =
 SUBDIRS = \
        in-house \
        text-rendering-tests \
+       aots \
        $(NULL)
 
 # Convenience targets:
index 5839d8c..78cdb1a 100644 (file)
@@ -96,8 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -304,6 +303,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -376,6 +377,7 @@ NULL =
 SUBDIRS = \
        in-house \
        text-rendering-tests \
+       aots \
        $(NULL)
 
 all: all-recursive
diff --git a/test/shaping/data/aots/COPYING b/test/shaping/data/aots/COPYING
new file mode 100644 (file)
index 0000000..d000f23
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright 2000-2016 Adobe Systems Incorporated. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use these files except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/test/shaping/data/aots/Makefile.am b/test/shaping/data/aots/Makefile.am
new file mode 100644 (file)
index 0000000..3b1faee
--- /dev/null
@@ -0,0 +1,37 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+
+# Convenience targets:
+lib:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+
+EXTRA_DIST = \
+       COPYING \
+       fonts \
+       $(TESTS) \
+       $(NULL)
+
+TEST_EXTENSIONS = .tests
+TESTS_LOG_COMPILER = $(srcdir)/../../run-tests.py $(top_builddir)/util/hb-shape$(EXEEXT)
+
+init-aots:
+       git clone https://github.com/adobe-type-tools/aots $(srcdir)/aots
+       make -C$(srcdir)/aots
+       make -C$(srcdir)/aots/harfbuzz
+       touch $(srcdir)/init-aots
+
+update-tests: init-aots lib
+       cp $(srcdir)/hb-aots-tester.cpp $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp
+       $(CXX) -Wno-narrowing $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp \
+               -I$(top_srcdir)/src/ -o $(srcdir)/aots/harfbuzz/aots \
+               -L$(top_builddir)/src/.libs -lharfbuzz
+       rm -rf $(srcdir)/tests/
+       mkdir $(srcdir)/tests/
+       export LD_LIBRARY_PATH=$(realpath $(top_builddir)/src/.libs); cd $(srcdir)/aots/harfbuzz; ./aots
+
+.PHONY: update-tests
+
+include Makefile.sources
+
+-include $(top_srcdir)/git.mk
diff --git a/test/shaping/data/aots/Makefile.in b/test/shaping/data/aots/Makefile.in
new file mode 100644 (file)
index 0000000..7cc5193
--- /dev/null
@@ -0,0 +1,1012 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Process this file with automake to produce Makefile.in
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = tests/classdef1_empty.tests tests/classdef1_multiple.tests \
+       tests/classdef1_single.tests tests/classdef1.tests \
+       tests/classdef2_empty.tests tests/classdef2_multiple.tests \
+       tests/classdef2_single.tests tests/classdef2.tests \
+       tests/gpos_chaining1_boundary.tests \
+       tests/gpos_chaining1_lookupflag.tests \
+       tests/gpos_chaining1_multiple_subrules.tests \
+       tests/gpos_chaining1_next_glyph.tests \
+       tests/gpos_chaining1_simple.tests \
+       tests/gpos_chaining1_successive.tests \
+       tests/gpos_chaining2_boundary.tests \
+       tests/gpos_chaining2_lookupflag.tests \
+       tests/gpos_chaining2_multiple_subrules.tests \
+       tests/gpos_chaining2_next_glyph.tests \
+       tests/gpos_chaining2_simple.tests \
+       tests/gpos_chaining2_successive.tests \
+       tests/gpos_chaining3_boundary.tests \
+       tests/gpos_chaining3_lookupflag.tests \
+       tests/gpos_chaining3_next_glyph.tests \
+       tests/gpos_chaining3_simple.tests \
+       tests/gpos_chaining3_successive.tests \
+       tests/gpos_context1_boundary.tests \
+       tests/gpos_context1_expansion.tests \
+       tests/gpos_context1_lookupflag.tests \
+       tests/gpos_context1_multiple_subrules.tests \
+       tests/gpos_context1_next_glyph.tests \
+       tests/gpos_context1_simple.tests \
+       tests/gpos_context1_successive.tests \
+       tests/gpos_context2_boundary.tests \
+       tests/gpos_context2_classes.tests \
+       tests/gpos_context2_expansion.tests \
+       tests/gpos_context2_lookupflag.tests \
+       tests/gpos_context2_multiple_subrules.tests \
+       tests/gpos_context2_next_glyph.tests \
+       tests/gpos_context2_simple.tests \
+       tests/gpos_context2_successive.tests \
+       tests/gpos_context3_boundary.tests \
+       tests/gpos_context3_lookupflag.tests \
+       tests/gpos_context3_next_glyph.tests \
+       tests/gpos_context3_simple.tests \
+       tests/gpos_context3_successive.tests \
+       tests/gpos1_1_lookupflag.tests tests/gpos1_1_simple.tests \
+       tests/gpos1_2_lookupflag.tests tests/gpos1_2.tests \
+       tests/gpos2_1_lookupflag.tests tests/gpos2_1_next_glyph.tests \
+       tests/gpos2_1_simple.tests tests/gpos2_1.tests \
+       tests/gpos2_2.tests tests/gpos3_lookupflag.tests \
+       tests/gpos3.tests tests/gpos4_lookupflag.tests \
+       tests/gpos4_multiple_anchors.tests tests/gpos4_simple.tests \
+       tests/gpos5.tests tests/gpos6.tests tests/gpos7_1.tests \
+       tests/gpos9.tests tests/gsub_chaining1_boundary.tests \
+       tests/gsub_chaining1_lookupflag.tests \
+       tests/gsub_chaining1_multiple_subrules.tests \
+       tests/gsub_chaining1_next_glyph.tests \
+       tests/gsub_chaining1_simple.tests \
+       tests/gsub_chaining1_successive.tests \
+       tests/gsub_chaining2_boundary.tests \
+       tests/gsub_chaining2_lookupflag.tests \
+       tests/gsub_chaining2_multiple_subrules.tests \
+       tests/gsub_chaining2_next_glyph.tests \
+       tests/gsub_chaining2_simple.tests \
+       tests/gsub_chaining2_successive.tests \
+       tests/gsub_chaining3_boundary.tests \
+       tests/gsub_chaining3_lookupflag.tests \
+       tests/gsub_chaining3_next_glyph.tests \
+       tests/gsub_chaining3_simple.tests \
+       tests/gsub_chaining3_successive.tests \
+       tests/gsub_context1_boundary.tests \
+       tests/gsub_context1_expansion.tests \
+       tests/gsub_context1_lookupflag.tests \
+       tests/gsub_context1_multiple_subrules.tests \
+       tests/gsub_context1_next_glyph.tests \
+       tests/gsub_context1_simple.tests \
+       tests/gsub_context1_successive.tests \
+       tests/gsub_context2_boundary.tests \
+       tests/gsub_context2_classes.tests \
+       tests/gsub_context2_expansion.tests \
+       tests/gsub_context2_lookupflag.tests \
+       tests/gsub_context2_multiple_subrules.tests \
+       tests/gsub_context2_next_glyph.tests \
+       tests/gsub_context2_simple.tests \
+       tests/gsub_context2_successive.tests \
+       tests/gsub_context3_boundary.tests \
+       tests/gsub_context3_lookupflag.tests \
+       tests/gsub_context3_next_glyph.tests \
+       tests/gsub_context3_simple.tests \
+       tests/gsub_context3_successive.tests \
+       tests/gsub1_1_lookupflag.tests tests/gsub1_1_modulo.tests \
+       tests/gsub1_1_simple.tests tests/gsub1_2_lookupflag.tests \
+       tests/gsub1_2_simple.tests tests/gsub2_1_lookupflag.tests \
+       tests/gsub2_1_multiple_sequences.tests \
+       tests/gsub2_1_simple.tests tests/gsub3_1_lookupflag.tests \
+       tests/gsub3_1_multiple.tests tests/gsub3_1_simple.tests \
+       tests/gsub4_1_lookupflag.tests \
+       tests/gsub4_1_multiple_ligatures.tests \
+       tests/gsub4_1_multiple_ligsets.tests \
+       tests/gsub4_1_simple.tests tests/gsub7.tests \
+       tests/lookupflag_ignore_attach.tests \
+       tests/lookupflag_ignore_base.tests \
+       tests/lookupflag_ignore_combination.tests \
+       tests/lookupflag_ignore_ligatures.tests \
+       tests/lookupflag_ignore_marks.tests $(am__EXEEXT_1)
+subdir = test/shaping/data/aots
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
+       $(top_srcdir)/m4/ax_code_coverage.m4 \
+       $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
+       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red='\e[0;31m'; \
+    grn='\e[0;32m'; \
+    lgn='\e[1;32m'; \
+    blu='\e[1;34m'; \
+    mgn='\e[0;35m'; \
+    brg='\e[1m'; \
+    std='\e[m'; \
+  fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__recheck_rx = ^[    ]*:recheck:[    ]*
+am__global_test_result_rx = ^[         ]*:global-test-result:[         ]*
+am__copy_in_global_log_rx = ^[         ]*:copy-in-global-log:[         ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+           recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[       ]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);                                     \
+$(am__vpath_adj_setup) $(am__vpath_adj)                        \
+$(am__tty_colors);                                     \
+srcdir=$(srcdir); export srcdir;                       \
+case "$@" in                                           \
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;   \
+    *) am__odir=.;;                                    \
+esac;                                                  \
+test "x$$am__odir" = x"." || test -d "$$am__odir"      \
+  || $(MKDIR_P) "$$am__odir" || exit $$?;              \
+if test -f "./$$f"; then dir=./;                       \
+elif test -f "$$f"; then dir=;                         \
+else dir="$(srcdir)/"; fi;                             \
+tst=$$dir$$f; log='$@';                                \
+if test -n '$(DISABLE_HARD_ERRORS)'; then              \
+  am__enable_hard_errors=no;                           \
+else                                                   \
+  am__enable_hard_errors=yes;                          \
+fi;                                                    \
+case " $(XFAIL_TESTS) " in                             \
+  *[\ \        ]$$f[\ \        ]* | *[\ \      ]$$dir$$f[\ \   ]*) \
+    am__expect_failure=yes;;                           \
+  *)                                                   \
+    am__expect_failure=no;;                            \
+esac;                                                  \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+am__EXEEXT_1 =
+TEST_SUITE_LOG = test-suite.log
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.tests.log=.log)
+TESTS_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TESTS_LOG_COMPILE = $(TESTS_LOG_COMPILER) $(AM_TESTS_LOG_FLAGS) \
+       $(TESTS_LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.sources \
+       $(top_srcdir)/test-driver COPYING
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_FT_CFLAGS = @CAIRO_FT_CFLAGS@
+CAIRO_FT_LIBS = @CAIRO_FT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
+CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
+CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
+CORETEXT_CFLAGS = @CORETEXT_CFLAGS@
+CORETEXT_LIBS = @CORETEXT_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DIRECTWRITE_CXXFLAGS = @DIRECTWRITE_CXXFLAGS@
+DIRECTWRITE_LIBS = @DIRECTWRITE_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_DEPS = @FREETYPE_DEPS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+GCOV = @GCOV@
+GENHTML = @GENHTML@
+GIT = @GIT@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_DEPS = @GLIB_DEPS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
+GOBJECT_LIBS = @GOBJECT_LIBS@
+GRAPHITE2_CFLAGS = @GRAPHITE2_CFLAGS@
+GRAPHITE2_DEPS = @GRAPHITE2_DEPS@
+GRAPHITE2_LIBS = @GRAPHITE2_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HB_LIBTOOL_VERSION_INFO = @HB_LIBTOOL_VERSION_INFO@
+HB_VERSION = @HB_VERSION@
+HB_VERSION_MAJOR = @HB_VERSION_MAJOR@
+HB_VERSION_MICRO = @HB_VERSION_MICRO@
+HB_VERSION_MINOR = @HB_VERSION_MINOR@
+HTML_DIR = @HTML_DIR@
+ICU_CFLAGS = @ICU_CFLAGS@
+ICU_CONFIG = @ICU_CONFIG@
+ICU_LIBS = @ICU_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RAGEL = @RAGEL@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UNISCRIBE_CFLAGS = @UNISCRIBE_CFLAGS@
+UNISCRIBE_LIBS = @UNISCRIBE_LIBS@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_gobject = @have_gobject@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL = 
+EXTRA_DIST = \
+       COPYING \
+       fonts \
+       $(TESTS) \
+       $(NULL)
+
+TEST_EXTENSIONS = .tests
+TESTS_LOG_COMPILER = $(srcdir)/../../run-tests.py $(top_builddir)/util/hb-shape$(EXEEXT)
+DISABLED_TESTS = \
+       $(NULL)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .log .tests .tests$(EXEEXT) .trs
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits test/shaping/data/aots/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnits test/shaping/data/aots/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+$(srcdir)/Makefile.sources $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+       rm -f $< $@
+       $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+       @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+       @$(am__set_TESTS_bases); \
+       am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+       redo_bases=`for i in $$bases; do \
+                     am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+                   done`; \
+       if test -n "$$redo_bases"; then \
+         redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+         redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+         if $(am__make_dryrun); then :; else \
+           rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+         fi; \
+       fi; \
+       if test -n "$$am__remaking_logs"; then \
+         echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+              "recursion detected" >&2; \
+       elif test -n "$$redo_logs"; then \
+         am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+       fi; \
+       if $(am__make_dryrun); then :; else \
+         st=0;  \
+         errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+         for i in $$redo_bases; do \
+           test -f $$i.trs && test -r $$i.trs \
+             || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+           test -f $$i.log && test -r $$i.log \
+             || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+         done; \
+         test $$st -eq 0 || exit 1; \
+       fi
+       @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+       ws='[   ]'; \
+       results=`for b in $$bases; do echo $$b.trs; done`; \
+       test -n "$$results" || results=/dev/null; \
+       all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+       pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+       fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+       skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+       xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+       xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+       error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+       if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+         success=true; \
+       else \
+         success=false; \
+       fi; \
+       br='==================='; br=$$br$$br$$br$$br; \
+       result_count () \
+       { \
+           if test x"$$1" = x"--maybe-color"; then \
+             maybe_colorize=yes; \
+           elif test x"$$1" = x"--no-color"; then \
+             maybe_colorize=no; \
+           else \
+             echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+           fi; \
+           shift; \
+           desc=$$1 count=$$2; \
+           if test $$maybe_colorize = yes && test $$count -gt 0; then \
+             color_start=$$3 color_end=$$std; \
+           else \
+             color_start= color_end=; \
+           fi; \
+           echo "$${color_start}# $$desc $$count$${color_end}"; \
+       }; \
+       create_testsuite_report () \
+       { \
+         result_count $$1 "TOTAL:" $$all   "$$brg"; \
+         result_count $$1 "PASS: " $$pass  "$$grn"; \
+         result_count $$1 "SKIP: " $$skip  "$$blu"; \
+         result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+         result_count $$1 "FAIL: " $$fail  "$$red"; \
+         result_count $$1 "XPASS:" $$xpass "$$red"; \
+         result_count $$1 "ERROR:" $$error "$$mgn"; \
+       }; \
+       {                                                               \
+         echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |       \
+           $(am__rst_title);                                           \
+         create_testsuite_report --no-color;                           \
+         echo;                                                         \
+         echo ".. contents:: :depth: 2";                               \
+         echo;                                                         \
+         for b in $$bases; do echo $$b; done                           \
+           | $(am__create_global_log);                                 \
+       } >$(TEST_SUITE_LOG).tmp || exit 1;                             \
+       mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);                     \
+       if $$success; then                                              \
+         col="$$grn";                                                  \
+        else                                                           \
+         col="$$red";                                                  \
+         test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);               \
+       fi;                                                             \
+       echo "$${col}$$br$${std}";                                      \
+       echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";   \
+       echo "$${col}$$br$${std}";                                      \
+       create_testsuite_report --maybe-color;                          \
+       echo "$$col$$br$$std";                                          \
+       if $$success; then :; else                                      \
+         echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";         \
+         if test -n "$(PACKAGE_BUGREPORT)"; then                       \
+           echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+         fi;                                                           \
+         echo "$$col$$br$$std";                                        \
+       fi;                                                             \
+       $$success || exit 1
+
+check-TESTS:
+       @list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+       @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+       log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+       exit $$?;
+recheck: all 
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       bases=`for i in $$bases; do echo $$i; done \
+                | $(am__list_recheck_tests)` || exit 1; \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       log_list=`echo $$log_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+               am__force_recheck=am--force-recheck \
+               TEST_LOGS="$$log_list"; \
+       exit $$?
+.tests.log:
+       @p='$<'; \
+       $(am__set_b); \
+       $(am__check_pre) $(TESTS_LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_TESTS_LOG_DRIVER_FLAGS) $(TESTS_LOG_DRIVER_FLAGS) -- $(TESTS_LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.tests$(EXEEXT).log:
+@am__EXEEXT_TRUE@      @p='$<'; \
+@am__EXEEXT_TRUE@      $(am__set_b); \
+@am__EXEEXT_TRUE@      $(am__check_pre) $(TESTS_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@      --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@      $(am__common_driver_flags) $(AM_TESTS_LOG_DRIVER_FLAGS) $(TESTS_LOG_DRIVER_FLAGS) -- $(TESTS_LOG_COMPILE) \
+@am__EXEEXT_TRUE@      "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+       -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+       -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+       -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am check check-TESTS check-am clean clean-generic \
+       clean-libtool cscopelist-am ctags-am distclean \
+       distclean-generic distclean-libtool distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am recheck tags-am \
+       uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Convenience targets:
+lib:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+
+init-aots:
+       git clone https://github.com/adobe-type-tools/aots $(srcdir)/aots
+       make -C$(srcdir)/aots
+       make -C$(srcdir)/aots/harfbuzz
+       touch $(srcdir)/init-aots
+
+update-tests: init-aots lib
+       cp $(srcdir)/hb-aots-tester.cpp $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp
+       $(CXX) -Wno-narrowing $(srcdir)/aots/harfbuzz/hb-aots-tester.cpp \
+               -I$(top_srcdir)/src/ -o $(srcdir)/aots/harfbuzz/aots \
+               -L$(top_builddir)/src/.libs -lharfbuzz
+       rm -rf $(srcdir)/tests/
+       mkdir $(srcdir)/tests/
+       export LD_LIBRARY_PATH=$(realpath $(top_builddir)/src/.libs); cd $(srcdir)/aots/harfbuzz; ./aots
+
+.PHONY: update-tests
+
+-include $(top_srcdir)/git.mk
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/test/shaping/data/aots/Makefile.sources b/test/shaping/data/aots/Makefile.sources
new file mode 100644 (file)
index 0000000..9339682
--- /dev/null
@@ -0,0 +1,126 @@
+TESTS = \
+       tests/classdef1_empty.tests \
+       tests/classdef1_multiple.tests \
+       tests/classdef1_single.tests \
+       tests/classdef1.tests \
+       tests/classdef2_empty.tests \
+       tests/classdef2_multiple.tests \
+       tests/classdef2_single.tests \
+       tests/classdef2.tests \
+       tests/gpos_chaining1_boundary.tests \
+       tests/gpos_chaining1_lookupflag.tests \
+       tests/gpos_chaining1_multiple_subrules.tests \
+       tests/gpos_chaining1_next_glyph.tests \
+       tests/gpos_chaining1_simple.tests \
+       tests/gpos_chaining1_successive.tests \
+       tests/gpos_chaining2_boundary.tests \
+       tests/gpos_chaining2_lookupflag.tests \
+       tests/gpos_chaining2_multiple_subrules.tests \
+       tests/gpos_chaining2_next_glyph.tests \
+       tests/gpos_chaining2_simple.tests \
+       tests/gpos_chaining2_successive.tests \
+       tests/gpos_chaining3_boundary.tests \
+       tests/gpos_chaining3_lookupflag.tests \
+       tests/gpos_chaining3_next_glyph.tests \
+       tests/gpos_chaining3_simple.tests \
+       tests/gpos_chaining3_successive.tests \
+       tests/gpos_context1_boundary.tests \
+       tests/gpos_context1_expansion.tests \
+       tests/gpos_context1_lookupflag.tests \
+       tests/gpos_context1_multiple_subrules.tests \
+       tests/gpos_context1_next_glyph.tests \
+       tests/gpos_context1_simple.tests \
+       tests/gpos_context1_successive.tests \
+       tests/gpos_context2_boundary.tests \
+       tests/gpos_context2_classes.tests \
+       tests/gpos_context2_expansion.tests \
+       tests/gpos_context2_lookupflag.tests \
+       tests/gpos_context2_multiple_subrules.tests \
+       tests/gpos_context2_next_glyph.tests \
+       tests/gpos_context2_simple.tests \
+       tests/gpos_context2_successive.tests \
+       tests/gpos_context3_boundary.tests \
+       tests/gpos_context3_lookupflag.tests \
+       tests/gpos_context3_next_glyph.tests \
+       tests/gpos_context3_simple.tests \
+       tests/gpos_context3_successive.tests \
+       tests/gpos1_1_lookupflag.tests \
+       tests/gpos1_1_simple.tests \
+       tests/gpos1_2_lookupflag.tests \
+       tests/gpos1_2.tests \
+       tests/gpos2_1_lookupflag.tests \
+       tests/gpos2_1_next_glyph.tests \
+       tests/gpos2_1_simple.tests \
+       tests/gpos2_1.tests \
+       tests/gpos2_2.tests \
+       tests/gpos3_lookupflag.tests \
+       tests/gpos3.tests \
+       tests/gpos4_lookupflag.tests \
+       tests/gpos4_multiple_anchors.tests \
+       tests/gpos4_simple.tests \
+       tests/gpos5.tests \
+       tests/gpos6.tests \
+       tests/gpos7_1.tests \
+       tests/gpos9.tests \
+       tests/gsub_chaining1_boundary.tests \
+       tests/gsub_chaining1_lookupflag.tests \
+       tests/gsub_chaining1_multiple_subrules.tests \
+       tests/gsub_chaining1_next_glyph.tests \
+       tests/gsub_chaining1_simple.tests \
+       tests/gsub_chaining1_successive.tests \
+       tests/gsub_chaining2_boundary.tests \
+       tests/gsub_chaining2_lookupflag.tests \
+       tests/gsub_chaining2_multiple_subrules.tests \
+       tests/gsub_chaining2_next_glyph.tests \
+       tests/gsub_chaining2_simple.tests \
+       tests/gsub_chaining2_successive.tests \
+       tests/gsub_chaining3_boundary.tests \
+       tests/gsub_chaining3_lookupflag.tests \
+       tests/gsub_chaining3_next_glyph.tests \
+       tests/gsub_chaining3_simple.tests \
+       tests/gsub_chaining3_successive.tests \
+       tests/gsub_context1_boundary.tests \
+       tests/gsub_context1_expansion.tests \
+       tests/gsub_context1_lookupflag.tests \
+       tests/gsub_context1_multiple_subrules.tests \
+       tests/gsub_context1_next_glyph.tests \
+       tests/gsub_context1_simple.tests \
+       tests/gsub_context1_successive.tests \
+       tests/gsub_context2_boundary.tests \
+       tests/gsub_context2_classes.tests \
+       tests/gsub_context2_expansion.tests \
+       tests/gsub_context2_lookupflag.tests \
+       tests/gsub_context2_multiple_subrules.tests \
+       tests/gsub_context2_next_glyph.tests \
+       tests/gsub_context2_simple.tests \
+       tests/gsub_context2_successive.tests \
+       tests/gsub_context3_boundary.tests \
+       tests/gsub_context3_lookupflag.tests \
+       tests/gsub_context3_next_glyph.tests \
+       tests/gsub_context3_simple.tests \
+       tests/gsub_context3_successive.tests \
+       tests/gsub1_1_lookupflag.tests \
+       tests/gsub1_1_modulo.tests \
+       tests/gsub1_1_simple.tests \
+       tests/gsub1_2_lookupflag.tests \
+       tests/gsub1_2_simple.tests \
+       tests/gsub2_1_lookupflag.tests \
+       tests/gsub2_1_multiple_sequences.tests \
+       tests/gsub2_1_simple.tests \
+       tests/gsub3_1_lookupflag.tests \
+       tests/gsub3_1_multiple.tests \
+       tests/gsub3_1_simple.tests \
+       tests/gsub4_1_lookupflag.tests \
+       tests/gsub4_1_multiple_ligatures.tests \
+       tests/gsub4_1_multiple_ligsets.tests \
+       tests/gsub4_1_simple.tests \
+       tests/gsub7.tests \
+       tests/lookupflag_ignore_attach.tests \
+       tests/lookupflag_ignore_base.tests \
+       tests/lookupflag_ignore_combination.tests \
+       tests/lookupflag_ignore_ligatures.tests \
+       tests/lookupflag_ignore_marks.tests \
+       $(NULL)
+
+DISABLED_TESTS = \
+       $(NULL)
diff --git a/test/shaping/data/aots/fonts/classdef1_font1.otf b/test/shaping/data/aots/fonts/classdef1_font1.otf
new file mode 100644 (file)
index 0000000..f0add69
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef1_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef1_font2.otf b/test/shaping/data/aots/fonts/classdef1_font2.otf
new file mode 100644 (file)
index 0000000..f01876d
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef1_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef1_font3.otf b/test/shaping/data/aots/fonts/classdef1_font3.otf
new file mode 100644 (file)
index 0000000..2a0f9cc
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef1_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef1_font4.otf b/test/shaping/data/aots/fonts/classdef1_font4.otf
new file mode 100644 (file)
index 0000000..9c0f41c
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef1_font4.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef2_font1.otf b/test/shaping/data/aots/fonts/classdef2_font1.otf
new file mode 100644 (file)
index 0000000..2e2faaf
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef2_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef2_font2.otf b/test/shaping/data/aots/fonts/classdef2_font2.otf
new file mode 100644 (file)
index 0000000..2e2a1af
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef2_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef2_font3.otf b/test/shaping/data/aots/fonts/classdef2_font3.otf
new file mode 100644 (file)
index 0000000..14c9119
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef2_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/classdef2_font4.otf b/test/shaping/data/aots/fonts/classdef2_font4.otf
new file mode 100644 (file)
index 0000000..c75c883
Binary files /dev/null and b/test/shaping/data/aots/fonts/classdef2_font4.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap0_font1.otf b/test/shaping/data/aots/fonts/cmap0_font1.otf
new file mode 100644 (file)
index 0000000..772f9a7
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap0_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap10_font1.otf b/test/shaping/data/aots/fonts/cmap10_font1.otf
new file mode 100644 (file)
index 0000000..023e945
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap10_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap10_font2.otf b/test/shaping/data/aots/fonts/cmap10_font2.otf
new file mode 100644 (file)
index 0000000..5202f79
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap10_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap12_font1.otf b/test/shaping/data/aots/fonts/cmap12_font1.otf
new file mode 100644 (file)
index 0000000..2d74b3a
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap12_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap14_font1.otf b/test/shaping/data/aots/fonts/cmap14_font1.otf
new file mode 100644 (file)
index 0000000..a8e941d
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap14_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap2_font1.otf b/test/shaping/data/aots/fonts/cmap2_font1.otf
new file mode 100644 (file)
index 0000000..a123d9c
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap2_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap4_font1.otf b/test/shaping/data/aots/fonts/cmap4_font1.otf
new file mode 100644 (file)
index 0000000..516ed8e
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap4_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap4_font2.otf b/test/shaping/data/aots/fonts/cmap4_font2.otf
new file mode 100644 (file)
index 0000000..0f678a3
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap4_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap4_font3.otf b/test/shaping/data/aots/fonts/cmap4_font3.otf
new file mode 100644 (file)
index 0000000..2034ecd
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap4_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap4_font4.otf b/test/shaping/data/aots/fonts/cmap4_font4.otf
new file mode 100644 (file)
index 0000000..450508e
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap4_font4.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap6_font1.otf b/test/shaping/data/aots/fonts/cmap6_font1.otf
new file mode 100644 (file)
index 0000000..10b64a7
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap6_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap6_font2.otf b/test/shaping/data/aots/fonts/cmap6_font2.otf
new file mode 100644 (file)
index 0000000..2d2957f
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap6_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap8_font1.otf b/test/shaping/data/aots/fonts/cmap8_font1.otf
new file mode 100644 (file)
index 0000000..791b9e3
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap8_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_composition_font1.otf b/test/shaping/data/aots/fonts/cmap_composition_font1.otf
new file mode 100644 (file)
index 0000000..c790717
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_composition_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_subtableselection_font1.otf b/test/shaping/data/aots/fonts/cmap_subtableselection_font1.otf
new file mode 100644 (file)
index 0000000..8929f8a
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_subtableselection_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_subtableselection_font2.otf b/test/shaping/data/aots/fonts/cmap_subtableselection_font2.otf
new file mode 100644 (file)
index 0000000..2611092
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_subtableselection_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_subtableselection_font3.otf b/test/shaping/data/aots/fonts/cmap_subtableselection_font3.otf
new file mode 100644 (file)
index 0000000..9f39331
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_subtableselection_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_subtableselection_font4.otf b/test/shaping/data/aots/fonts/cmap_subtableselection_font4.otf
new file mode 100644 (file)
index 0000000..83ae88e
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_subtableselection_font4.otf differ
diff --git a/test/shaping/data/aots/fonts/cmap_subtableselection_font5.otf b/test/shaping/data/aots/fonts/cmap_subtableselection_font5.otf
new file mode 100644 (file)
index 0000000..8b614ad
Binary files /dev/null and b/test/shaping/data/aots/fonts/cmap_subtableselection_font5.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos1_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..3245425
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_1_simple_f1.otf b/test/shaping/data/aots/fonts/gpos1_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..c5f8888
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_1_simple_f2.otf b/test/shaping/data/aots/fonts/gpos1_1_simple_f2.otf
new file mode 100644 (file)
index 0000000..905d0a3
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_1_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_1_simple_f3.otf b/test/shaping/data/aots/fonts/gpos1_1_simple_f3.otf
new file mode 100644 (file)
index 0000000..550be87
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_1_simple_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_1_simple_f4.otf b/test/shaping/data/aots/fonts/gpos1_1_simple_f4.otf
new file mode 100644 (file)
index 0000000..448bc8b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_1_simple_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_2_font1.otf b/test/shaping/data/aots/fonts/gpos1_2_font1.otf
new file mode 100644 (file)
index 0000000..3e7b7bc
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_2_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos1_2_font2.otf b/test/shaping/data/aots/fonts/gpos1_2_font2.otf
new file mode 100644 (file)
index 0000000..ba9d224
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos1_2_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_font6.otf b/test/shaping/data/aots/fonts/gpos2_1_font6.otf
new file mode 100644 (file)
index 0000000..cd4ea94
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_font6.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_font7.otf b/test/shaping/data/aots/fonts/gpos2_1_font7.otf
new file mode 100644 (file)
index 0000000..2871acc
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_font7.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..6003782
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..9d0a273
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..64d6c2c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f2.otf b/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f2.otf
new file mode 100644 (file)
index 0000000..3d8c37a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_next_glyph_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_1_simple_f1.otf b/test/shaping/data/aots/fonts/gpos2_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..c947776
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_2_font1.otf b/test/shaping/data/aots/fonts/gpos2_2_font1.otf
new file mode 100644 (file)
index 0000000..dde370a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_2_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_2_font2.otf b/test/shaping/data/aots/fonts/gpos2_2_font2.otf
new file mode 100644 (file)
index 0000000..63d874a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_2_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_2_font3.otf b/test/shaping/data/aots/fonts/gpos2_2_font3.otf
new file mode 100644 (file)
index 0000000..b530676
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_2_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_2_font4.otf b/test/shaping/data/aots/fonts/gpos2_2_font4.otf
new file mode 100644 (file)
index 0000000..b549e02
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_2_font4.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos2_2_font5.otf b/test/shaping/data/aots/fonts/gpos2_2_font5.otf
new file mode 100644 (file)
index 0000000..64c40bb
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos2_2_font5.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos3_font1.otf b/test/shaping/data/aots/fonts/gpos3_font1.otf
new file mode 100644 (file)
index 0000000..9b6d39a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos3_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos3_font2.otf b/test/shaping/data/aots/fonts/gpos3_font2.otf
new file mode 100644 (file)
index 0000000..dee5785
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos3_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos3_font3.otf b/test/shaping/data/aots/fonts/gpos3_font3.otf
new file mode 100644 (file)
index 0000000..7522660
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos3_font3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos4_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos4_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..b141116
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos4_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos4_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gpos4_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..84e4843
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos4_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos4_multiple_anchors_1.otf b/test/shaping/data/aots/fonts/gpos4_multiple_anchors_1.otf
new file mode 100644 (file)
index 0000000..025f69b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos4_multiple_anchors_1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos4_simple_1.otf b/test/shaping/data/aots/fonts/gpos4_simple_1.otf
new file mode 100644 (file)
index 0000000..da54a1f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos4_simple_1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos5_font1.otf b/test/shaping/data/aots/fonts/gpos5_font1.otf
new file mode 100644 (file)
index 0000000..8c48fb6
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos5_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos6_font1.otf b/test/shaping/data/aots/fonts/gpos6_font1.otf
new file mode 100644 (file)
index 0000000..f7f92cc
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos6_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos7_1_font1.otf b/test/shaping/data/aots/fonts/gpos7_1_font1.otf
new file mode 100644 (file)
index 0000000..ced8907
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos7_1_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos9_font1.otf b/test/shaping/data/aots/fonts/gpos9_font1.otf
new file mode 100644 (file)
index 0000000..e99c25a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos9_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos9_font2.otf b/test/shaping/data/aots/fonts/gpos9_font2.otf
new file mode 100644 (file)
index 0000000..9ae824b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos9_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f1.otf
new file mode 100644 (file)
index 0000000..44c4117
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f2.otf
new file mode 100644 (file)
index 0000000..431b08f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f3.otf b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f3.otf
new file mode 100644 (file)
index 0000000..1bac49a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f4.otf b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f4.otf
new file mode 100644 (file)
index 0000000..3d37782
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..a83342a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..07bf55c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..dc3754b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..17852c2
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_simple_f1.otf
new file mode 100644 (file)
index 0000000..31cbe77
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_simple_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining1_simple_f2.otf
new file mode 100644 (file)
index 0000000..3293ad8
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining1_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining1_successive_f1.otf
new file mode 100644 (file)
index 0000000..4c86663
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining1_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f1.otf
new file mode 100644 (file)
index 0000000..49210fb
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f2.otf
new file mode 100644 (file)
index 0000000..456fc9b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f3.otf b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f3.otf
new file mode 100644 (file)
index 0000000..768492a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f4.otf b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f4.otf
new file mode 100644 (file)
index 0000000..2670da6
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..e8cce56
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..f182c7f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..d24896a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..f6bbda4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_simple_f1.otf
new file mode 100644 (file)
index 0000000..1805a03
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_simple_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining2_simple_f2.otf
new file mode 100644 (file)
index 0000000..1df12f5
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining2_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining2_successive_f1.otf
new file mode 100644 (file)
index 0000000..a3aadaf
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining2_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f1.otf
new file mode 100644 (file)
index 0000000..4f13bdd
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f2.otf
new file mode 100644 (file)
index 0000000..48be5dd
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f3.otf b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f3.otf
new file mode 100644 (file)
index 0000000..a10068b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f4.otf b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f4.otf
new file mode 100644 (file)
index 0000000..8030ac0
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining3_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..7864ce0
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining3_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..20a7966
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining3_simple_f1.otf
new file mode 100644 (file)
index 0000000..2c63328
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_simple_f2.otf b/test/shaping/data/aots/fonts/gpos_chaining3_simple_f2.otf
new file mode 100644 (file)
index 0000000..6ef8fb1
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_chaining3_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_chaining3_successive_f1.otf
new file mode 100644 (file)
index 0000000..8e8439d
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_chaining3_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_boundary_f1.otf
new file mode 100644 (file)
index 0000000..22bb3ea
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_context1_boundary_f2.otf
new file mode 100644 (file)
index 0000000..7e4c0e1
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_expansion_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_expansion_f1.otf
new file mode 100644 (file)
index 0000000..f7c60f6
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_expansion_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..e9b03ae
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..b9998cd
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..6f1aafa
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..ed9a387
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..6007d54
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_simple_f1.otf
new file mode 100644 (file)
index 0000000..5e6cd9e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_simple_f2.otf b/test/shaping/data/aots/fonts/gpos_context1_simple_f2.otf
new file mode 100644 (file)
index 0000000..b4fddb3
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context1_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_context1_successive_f1.otf
new file mode 100644 (file)
index 0000000..eb0f962
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context1_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_boundary_f1.otf
new file mode 100644 (file)
index 0000000..3fce497
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_context2_boundary_f2.otf
new file mode 100644 (file)
index 0000000..5b4e012
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_classes_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_classes_f1.otf
new file mode 100644 (file)
index 0000000..585b511
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_classes_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_classes_f2.otf b/test/shaping/data/aots/fonts/gpos_context2_classes_f2.otf
new file mode 100644 (file)
index 0000000..411d58e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_classes_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_expansion_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_expansion_f1.otf
new file mode 100644 (file)
index 0000000..4b2d36a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_expansion_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..1c0c480
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..bf20d84
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..05b6b73
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..f79712c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..1b5a256
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_simple_f1.otf
new file mode 100644 (file)
index 0000000..9aaec44
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_simple_f2.otf b/test/shaping/data/aots/fonts/gpos_context2_simple_f2.otf
new file mode 100644 (file)
index 0000000..c789b2e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context2_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_context2_successive_f1.otf
new file mode 100644 (file)
index 0000000..b89bfb7
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context2_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_boundary_f1.otf b/test/shaping/data/aots/fonts/gpos_context3_boundary_f1.otf
new file mode 100644 (file)
index 0000000..f8949d4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_boundary_f2.otf b/test/shaping/data/aots/fonts/gpos_context3_boundary_f2.otf
new file mode 100644 (file)
index 0000000..ceb7452
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..40b55ee
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..bcf4d17
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gpos_context3_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..6f9d919
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_simple_f1.otf b/test/shaping/data/aots/fonts/gpos_context3_simple_f1.otf
new file mode 100644 (file)
index 0000000..470c2ed
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gpos_context3_successive_f1.otf b/test/shaping/data/aots/fonts/gpos_context3_successive_f1.otf
new file mode 100644 (file)
index 0000000..aeb9bbd
Binary files /dev/null and b/test/shaping/data/aots/fonts/gpos_context3_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub1_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub1_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..a539b95
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub1_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub1_1_modulo_f1.otf b/test/shaping/data/aots/fonts/gsub1_1_modulo_f1.otf
new file mode 100644 (file)
index 0000000..7ba2379
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub1_1_modulo_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub1_1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub1_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..c21fcd3
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub1_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub1_2_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub1_2_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..b13af6e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub1_2_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub1_2_simple_f1.otf b/test/shaping/data/aots/fonts/gsub1_2_simple_f1.otf
new file mode 100644 (file)
index 0000000..d3851b3
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub1_2_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub2_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub2_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..8330ad4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub2_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub2_1_multiple_sequences_f1.otf b/test/shaping/data/aots/fonts/gsub2_1_multiple_sequences_f1.otf
new file mode 100644 (file)
index 0000000..c912937
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub2_1_multiple_sequences_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub2_1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub2_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..584a7f5
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub2_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub3_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub3_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..4ccf55f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub3_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub3_1_multiple_f1.otf b/test/shaping/data/aots/fonts/gsub3_1_multiple_f1.otf
new file mode 100644 (file)
index 0000000..075f196
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub3_1_multiple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub3_1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub3_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..201f0f2
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub3_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub4_1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub4_1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..08ec01a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub4_1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f1.otf b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f1.otf
new file mode 100644 (file)
index 0000000..90da331
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f2.otf b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f2.otf
new file mode 100644 (file)
index 0000000..4383ba9
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligatures_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub4_1_multiple_ligsets_f1.otf b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligsets_f1.otf
new file mode 100644 (file)
index 0000000..cea1b1a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub4_1_multiple_ligsets_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub4_1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub4_1_simple_f1.otf
new file mode 100644 (file)
index 0000000..50c713a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub4_1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub7_font1.otf b/test/shaping/data/aots/fonts/gsub7_font1.otf
new file mode 100644 (file)
index 0000000..b920398
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub7_font1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub7_font2.otf b/test/shaping/data/aots/fonts/gsub7_font2.otf
new file mode 100644 (file)
index 0000000..c98bafb
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub7_font2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f1.otf
new file mode 100644 (file)
index 0000000..444d931
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f2.otf
new file mode 100644 (file)
index 0000000..2268647
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f3.otf b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f3.otf
new file mode 100644 (file)
index 0000000..a592947
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f4.otf b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f4.otf
new file mode 100644 (file)
index 0000000..f3f6b8c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..47e4c64
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..741362c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..67801f2
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..655000a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_simple_f1.otf
new file mode 100644 (file)
index 0000000..c770965
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_simple_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining1_simple_f2.otf
new file mode 100644 (file)
index 0000000..8999e3f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining1_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining1_successive_f1.otf
new file mode 100644 (file)
index 0000000..ad472ec
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining1_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f1.otf
new file mode 100644 (file)
index 0000000..845c256
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f2.otf
new file mode 100644 (file)
index 0000000..af0ad1f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f3.otf b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f3.otf
new file mode 100644 (file)
index 0000000..28679c8
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f4.otf b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f4.otf
new file mode 100644 (file)
index 0000000..14746c6
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..2f4feed
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..6edeb6b
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..ae0298f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..878666f
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_simple_f1.otf
new file mode 100644 (file)
index 0000000..e860930
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_simple_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining2_simple_f2.otf
new file mode 100644 (file)
index 0000000..4fdde33
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining2_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining2_successive_f1.otf
new file mode 100644 (file)
index 0000000..90f9f73
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining2_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f1.otf
new file mode 100644 (file)
index 0000000..1aea8be
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f2.otf
new file mode 100644 (file)
index 0000000..97c92c3
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f3.otf b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f3.otf
new file mode 100644 (file)
index 0000000..3b8513e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f3.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f4.otf b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f4.otf
new file mode 100644 (file)
index 0000000..e81d00e
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_boundary_f4.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining3_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..47c1007
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining3_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..9160eda
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining3_simple_f1.otf
new file mode 100644 (file)
index 0000000..5982eb5
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_simple_f2.otf b/test/shaping/data/aots/fonts/gsub_chaining3_simple_f2.otf
new file mode 100644 (file)
index 0000000..359b126
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_chaining3_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_chaining3_successive_f1.otf
new file mode 100644 (file)
index 0000000..ae39d92
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_chaining3_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_boundary_f1.otf
new file mode 100644 (file)
index 0000000..0267cab
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_context1_boundary_f2.otf
new file mode 100644 (file)
index 0000000..24b1716
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_expansion_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_expansion_f1.otf
new file mode 100644 (file)
index 0000000..c1dda80
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_expansion_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..60676ab
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..bcb56e4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..52cd861
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..891356a
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..2786ded
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_simple_f1.otf
new file mode 100644 (file)
index 0000000..ebdaf22
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_simple_f2.otf b/test/shaping/data/aots/fonts/gsub_context1_simple_f2.otf
new file mode 100644 (file)
index 0000000..d4a3fbf
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context1_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_context1_successive_f1.otf
new file mode 100644 (file)
index 0000000..ce2dce5
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context1_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_boundary_f1.otf
new file mode 100644 (file)
index 0000000..6f46192
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_context2_boundary_f2.otf
new file mode 100644 (file)
index 0000000..ef19d87
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_classes_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_classes_f1.otf
new file mode 100644 (file)
index 0000000..8507760
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_classes_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_classes_f2.otf b/test/shaping/data/aots/fonts/gsub_context2_classes_f2.otf
new file mode 100644 (file)
index 0000000..ceb74b2
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_classes_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_expansion_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_expansion_f1.otf
new file mode 100644 (file)
index 0000000..c12f0ac
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_expansion_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..a0fada4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..cd40a5d
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f1.otf
new file mode 100644 (file)
index 0000000..53be20d
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f2.otf b/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f2.otf
new file mode 100644 (file)
index 0000000..6bcc0cb
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_multiple_subrules_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..4ca4e48
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_simple_f1.otf
new file mode 100644 (file)
index 0000000..16aae9d
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_simple_f2.otf b/test/shaping/data/aots/fonts/gsub_context2_simple_f2.otf
new file mode 100644 (file)
index 0000000..fc31262
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_simple_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context2_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_context2_successive_f1.otf
new file mode 100644 (file)
index 0000000..cf1a89c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context2_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_boundary_f1.otf b/test/shaping/data/aots/fonts/gsub_context3_boundary_f1.otf
new file mode 100644 (file)
index 0000000..01cd29d
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_boundary_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_boundary_f2.otf b/test/shaping/data/aots/fonts/gsub_context3_boundary_f2.otf
new file mode 100644 (file)
index 0000000..6fa5f05
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_boundary_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f1.otf b/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f1.otf
new file mode 100644 (file)
index 0000000..94371b4
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f2.otf b/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f2.otf
new file mode 100644 (file)
index 0000000..d8150df
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_lookupflag_f2.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_next_glyph_f1.otf b/test/shaping/data/aots/fonts/gsub_context3_next_glyph_f1.otf
new file mode 100644 (file)
index 0000000..93533b8
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_next_glyph_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_simple_f1.otf b/test/shaping/data/aots/fonts/gsub_context3_simple_f1.otf
new file mode 100644 (file)
index 0000000..a1cd98c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_simple_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/gsub_context3_successive_f1.otf b/test/shaping/data/aots/fonts/gsub_context3_successive_f1.otf
new file mode 100644 (file)
index 0000000..d8b3d5c
Binary files /dev/null and b/test/shaping/data/aots/fonts/gsub_context3_successive_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/lookupflag_ignore_attach_f1.otf b/test/shaping/data/aots/fonts/lookupflag_ignore_attach_f1.otf
new file mode 100644 (file)
index 0000000..80651f1
Binary files /dev/null and b/test/shaping/data/aots/fonts/lookupflag_ignore_attach_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/lookupflag_ignore_base_f1.otf b/test/shaping/data/aots/fonts/lookupflag_ignore_base_f1.otf
new file mode 100644 (file)
index 0000000..3c242b0
Binary files /dev/null and b/test/shaping/data/aots/fonts/lookupflag_ignore_base_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/lookupflag_ignore_combination_f1.otf b/test/shaping/data/aots/fonts/lookupflag_ignore_combination_f1.otf
new file mode 100644 (file)
index 0000000..b88359a
Binary files /dev/null and b/test/shaping/data/aots/fonts/lookupflag_ignore_combination_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/lookupflag_ignore_ligatures_f1.otf b/test/shaping/data/aots/fonts/lookupflag_ignore_ligatures_f1.otf
new file mode 100644 (file)
index 0000000..1dc0c23
Binary files /dev/null and b/test/shaping/data/aots/fonts/lookupflag_ignore_ligatures_f1.otf differ
diff --git a/test/shaping/data/aots/fonts/lookupflag_ignore_marks_f1.otf b/test/shaping/data/aots/fonts/lookupflag_ignore_marks_f1.otf
new file mode 100644 (file)
index 0000000..aa429de
Binary files /dev/null and b/test/shaping/data/aots/fonts/lookupflag_ignore_marks_f1.otf differ
diff --git a/test/shaping/data/aots/tests/classdef1.tests b/test/shaping/data/aots/tests/classdef1.tests
new file mode 100644 (file)
index 0000000..40ded45
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef1_font4.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18|19|20|21]
diff --git a/test/shaping/data/aots/tests/classdef1_empty.tests b/test/shaping/data/aots/tests/classdef1_empty.tests
new file mode 100644 (file)
index 0000000..71d87f1
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef1_font2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|25|21]
diff --git a/test/shaping/data/aots/tests/classdef1_multiple.tests b/test/shaping/data/aots/tests/classdef1_multiple.tests
new file mode 100644 (file)
index 0000000..c813f49
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef1_font3.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+001B,U+001C,U+001D,U+001E,U+001F,U+0020,U+0021,U+0022,U+0023,U+0024:[20|23|24|25|24|26|27|28|28|29|30|31|34|33|34|35|37|38|38|39]
diff --git a/test/shaping/data/aots/tests/classdef1_single.tests b/test/shaping/data/aots/tests/classdef1_single.tests
new file mode 100644 (file)
index 0000000..b0196d3
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef2_font1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|25|21]
diff --git a/test/shaping/data/aots/tests/classdef2.tests b/test/shaping/data/aots/tests/classdef2.tests
new file mode 100644 (file)
index 0000000..d8c7b14
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef2_font4.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18|19|20|21]
diff --git a/test/shaping/data/aots/tests/classdef2_empty.tests b/test/shaping/data/aots/tests/classdef2_empty.tests
new file mode 100644 (file)
index 0000000..a8fd629
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef2_font2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|25|21]
diff --git a/test/shaping/data/aots/tests/classdef2_multiple.tests b/test/shaping/data/aots/tests/classdef2_multiple.tests
new file mode 100644 (file)
index 0000000..39e6835
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef2_font3.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+001B,U+001C,U+001D,U+001E,U+001F,U+0020,U+0021,U+0022,U+0023,U+0024:[20|23|24|25|24|26|27|28|28|29|30|31|34|33|34|35|37|38|38|39]
diff --git a/test/shaping/data/aots/tests/classdef2_single.tests b/test/shaping/data/aots/tests/classdef2_single.tests
new file mode 100644 (file)
index 0000000..b0196d3
--- /dev/null
@@ -0,0 +1 @@
+../fonts/classdef2_font1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|25|21]
diff --git a/test/shaping/data/aots/tests/gpos1_1_lookupflag.tests b/test/shaping/data/aots/tests/gpos1_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..88d7dd7
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos1_1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1500,0|19@3000,0|20@4200,0|21@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos1_1_simple.tests b/test/shaping/data/aots/tests/gpos1_1_simple.tests
new file mode 100644 (file)
index 0000000..101da9c
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gpos1_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1300,0|19@3000,0|20@4300,0|21@6000,0]
+../fonts/gpos1_1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1500,-200|19@3000,0|20@4500,-200|21@6000,0]
+../fonts/gpos1_1_simple_f3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1500,0|19@2800,0|20@4300,0|21@5600,0]
+#../fonts/gpos1_1_simple_f4.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1500,0|19@3000,-200|20@4500,-200|21@6000,-400]
diff --git a/test/shaping/data/aots/tests/gpos1_2.tests b/test/shaping/data/aots/tests/gpos1_2.tests
new file mode 100644 (file)
index 0000000..3ddfa44
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos1_2_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1300,0|19@3000,0|20@4200,0|21@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos1_2_lookupflag.tests b/test/shaping/data/aots/tests/gpos1_2_lookupflag.tests
new file mode 100644 (file)
index 0000000..82bcc43
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos1_2_font2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1500,0|19@3000,0|20@4200,0|21@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos2_1.tests b/test/shaping/data/aots/tests/gpos2_1.tests
new file mode 100644 (file)
index 0000000..4d8b5e9
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos2_1_font6.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011,U+0012,U+0014,U+0011:[17|18@1300,0|19@3000,-100|17@4500,0|18@5700,0|20@7500,-400|17@9000,0]
+../fonts/gpos2_1_font7.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011,U+0012,U+0014,U+0011,U+0015,U+0016,U+0011:[17|18@1300,0|19@3000,-100|17@4500,0|18@5700,0|20@7500,-400|17@9000,0|21@10000,0|22@12000,-600|17@13500,0]
diff --git a/test/shaping/data/aots/tests/gpos2_1_lookupflag.tests b/test/shaping/data/aots/tests/gpos2_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..ce445a1
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos2_1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0011,U+0013,U+0012,U+0014,U+0011:[17|19@1300,0|20@3000,-100|17@4500,0|19@5800,0|18@7500,0|20@9000,-100|17@10500,0]
+../fonts/gpos2_1_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0011,U+0013,U+0012,U+0014,U+0011:[17|19@1500,0|20@2800,-100|17@4300,0|19@5800,0|18@7100,0|20@8600,-100|17@10100,0]
diff --git a/test/shaping/data/aots/tests/gpos2_1_next_glyph.tests b/test/shaping/data/aots/tests/gpos2_1_next_glyph.tests
new file mode 100644 (file)
index 0000000..7f27eee
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos2_1_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0012,U+0012,U+0012,U+0012:[18@-100,0|18@1500,-100|18@2900,0|18@4500,-100]
+../fonts/gpos2_1_next_glyph_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0012,U+0012,U+0012,U+0012:[18@-100,0|18@1400,0|18@2900,0|18@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos2_1_simple.tests b/test/shaping/data/aots/tests/gpos2_1_simple.tests
new file mode 100644 (file)
index 0000000..71e8c81
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos2_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011,U+0012,U+0014:[17|18@1300,0|19@3000,-100|17@4500,0|18@6000,0|20@7500,0]
+../fonts/gpos2_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012:[17|18@1500,0]
diff --git a/test/shaping/data/aots/tests/gpos2_2.tests b/test/shaping/data/aots/tests/gpos2_2.tests
new file mode 100644 (file)
index 0000000..7be07f7
--- /dev/null
@@ -0,0 +1,5 @@
+../fonts/gpos2_2_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011,U+0012,U+0014:[17|18@1300,0|19@3000,-100|17@4500,0|18@6000,0|20@7500,0]
+../fonts/gpos2_2_font2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0011,U+0013,U+0012,U+0014,U+0011:[17|19@1300,0|20@3000,-100|17@4500,0|19@5800,0|18@7500,0|20@9000,-100|17@10500,0]
+../fonts/gpos2_2_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0011,U+0013,U+0012,U+0014,U+0011:[17|19@1500,0|20@2800,-100|17@4300,0|19@5800,0|18@7100,0|20@8600,-100|17@10100,0]
+../fonts/gpos2_2_font4.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0012,U+0012,U+0012,U+0012:[18@-100,0|18@1500,-100|18@2900,0|18@4500,-100]
+../fonts/gpos2_2_font5.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0012,U+0012,U+0012,U+0012:[18@-100,0|18@1400,0|18@2900,0|18@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos3.tests b/test/shaping/data/aots/tests/gpos3.tests
new file mode 100644 (file)
index 0000000..d6f37bf
--- /dev/null
@@ -0,0 +1,11 @@
+#../fonts/gpos3_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|19@1599,99|17@4500,0]
+../fonts/gpos3_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0011,U+0013,U+0011:[17|18@1500,0|17@3000,0|19@4500,0|17@6000,0]
+#../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0012,U+0011:[17|18@1500,0|18@1600,100|17@4500,0]
+#../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|19@1599,99|17@4500,0]
+#../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0014,U+0012,U+0011:[17|20@1500,0|18@1602,102|17@4500,0]
+#../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0014,U+0013,U+0011:[17|20@1500,0|19@1601,101|17@4500,0]
+../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0014,U+0011:[17|18@1500,0|20@3000,0|17@4500,0]
+../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0012,U+0011:[17|19@1500,0|18@3000,0|17@4500,0]
+../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0011:[17|19@1500,0|20@3000,0|17@4500,0]
+../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012:[17|18@1500,0]
+../fonts/gpos3_font3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0015,U+0015,U+0015:[17|18@1500,0|21@3000,0|21@4500,0|21@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos3_lookupflag.tests b/test/shaping/data/aots/tests/gpos3_lookupflag.tests
new file mode 100644 (file)
index 0000000..13d593c
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos3_font2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0015,U+0013,U+0011:[17|18@1500,0|21@3000,0|19@1599,99|17@6000,0]
+#../fonts/gpos3_font2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0015,U+0015,U+0015,U+0013,U+0011:[17|18@1500,0|21@3000,0|21@4500,0|21@6000,0|19@1599,99|17@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos4_lookupflag.tests b/test/shaping/data/aots/tests/gpos4_lookupflag.tests
new file mode 100644 (file)
index 0000000..9d041bf
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos4_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0011,U+0013,U+0011:[17|18@1500,0|17@3000,0|19@4500,0|17@6000,0]
+#../fonts/gpos4_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|19@3000,0|17@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos4_multiple_anchors.tests b/test/shaping/data/aots/tests/gpos4_multiple_anchors.tests
new file mode 100644 (file)
index 0000000..af9a1f5
--- /dev/null
@@ -0,0 +1 @@
+#../fonts/gpos4_multiple_anchors_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0013,U+0014,U+0015,U+0016,U+0012,U+0013,U+0014,U+0015,U+0016:[17|19@-100,-80|20@-91,-71|21@-102,-82|22@-93,-73|18@7500,0|19@7420,-60|20@7429,-51|21@7418,-62|22@7427,-53]
diff --git a/test/shaping/data/aots/tests/gpos4_simple.tests b/test/shaping/data/aots/tests/gpos4_simple.tests
new file mode 100644 (file)
index 0000000..5d60507
--- /dev/null
@@ -0,0 +1,5 @@
+#../fonts/gpos4_simple_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|19@1400,-80|17@4500,0]
+#../fonts/gpos4_simple_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0011,U+0013,U+0011:[17|17@1500,0|19@3000,0|17@4500,0]
+#../fonts/gpos4_simple_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0019,U+0019,U+0013,U+0011:[25|25@1500,0|19@3000,0|17@4500,0]
+#../fonts/gpos4_simple_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0013,U+0011:[17|18@1500,0|19@1400,-80|19@1400,-80|17@6000,0]
+#../fonts/gpos4_simple_1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0014,U+0013,U+0011:[17|18@1500,0|20@3000,0|19@1400,-80|17@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos5.tests b/test/shaping/data/aots/tests/gpos5.tests
new file mode 100644 (file)
index 0000000..a20a0b9
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos5_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+001E,U+0013,U+001F,U+0011:[17|18@1500,0|19@1400,-80|17@4500,0]
+#../fonts/gpos5_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+001E,U+001F,U+0013,U+0011:[17|18@1500,0|19@1401,-79|17@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos6.tests b/test/shaping/data/aots/tests/gpos6.tests
new file mode 100644 (file)
index 0000000..e5f9b3c
--- /dev/null
@@ -0,0 +1,3 @@
+#../fonts/gpos6_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|19@1400,-80|17@4500,0]
+#../fonts/gpos6_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0011,U+0013,U+0011:[17|17@1500,0|19@3000,0|17@4500,0]
+#../fonts/gpos6_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0014,U+0014,U+0013,U+0011:[20|20@1500,0|19@3000,0|17@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos7_1.tests b/test/shaping/data/aots/tests/gpos7_1.tests
new file mode 100644 (file)
index 0000000..954c8cb
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos7_1_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1600,0|19@3200,0|20@4800,0|21@6000,0]
+../fonts/gpos7_1_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0011,U+0012,U+0013,U+0011:[17|18@1500,0|17@3000,0|18@4500,0|19@6000,0|17@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos9.tests b/test/shaping/data/aots/tests/gpos9.tests
new file mode 100644 (file)
index 0000000..cb20333
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos9_font1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18@1300,0|19@3000,0|20@4300,0|21@6000,0]
+../fonts/gpos9_font2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0011,U+0012,U+0013,U+0014,U+0015,U+0011:[17|18@1300,0|19@2700,0|20@4300,0|21@5700,0|17@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_boundary.tests b/test/shaping/data/aots/tests/gpos_chaining1_boundary.tests
new file mode 100644 (file)
index 0000000..646ff2c
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gpos_chaining1_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining1_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining1_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining1_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_lookupflag.tests b/test/shaping/data/aots/tests/gpos_chaining1_lookupflag.tests
new file mode 100644 (file)
index 0000000..d0e6e2e
--- /dev/null
@@ -0,0 +1 @@
+#../fonts/gpos_chaining1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20@1500,0|90@3000,0|21@4500,0|91@6000,0|22@7500,0|92@9000,0|23@10520,0|93@12000,0|94@13500,0|24@15000,0|90@16500,0|25@18000,0|91@19500,0|26@21000,0|0@22500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_multiple_subrules.tests b/test/shaping/data/aots/tests/gpos_chaining1_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..51bbe03
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_chaining1_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|24@7500,0|0@9000,0|20@10500,0|21@12000,0|22@13520,0|23@15000,0|0@16500,0]
+../fonts/gpos_chaining1_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|24@7500,0|0@9000,0|20@10500,0|21@12000,0|22@13520,0|23@15000,0|0@16500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_next_glyph.tests b/test/shaping/data/aots/tests/gpos_chaining1_next_glyph.tests
new file mode 100644 (file)
index 0000000..f8be404
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining1_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6020,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_simple.tests b/test/shaping/data/aots/tests/gpos_chaining1_simple.tests
new file mode 100644 (file)
index 0000000..37efa11
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gpos_chaining1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|0@10500,0|0@12000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22@1500,0|23@3000,0|24@4500,0|25@6000,0|26@7500,0|0@9000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23@1500,0|24@3000,0|25@4500,0|26@6000,0|0@7500,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|0@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0]
+../fonts/gpos_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016:[0|20@1500,0|21@3000,0|22@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining1_successive.tests b/test/shaping/data/aots/tests/gpos_chaining1_successive.tests
new file mode 100644 (file)
index 0000000..7a829cf
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining1_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25@1500,0|20@3000,0|21@4520,0|22@6020,0|23@7500,0|24@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_boundary.tests b/test/shaping/data/aots/tests/gpos_chaining2_boundary.tests
new file mode 100644 (file)
index 0000000..c35b8c7
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gpos_chaining2_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining2_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining2_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining2_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_lookupflag.tests b/test/shaping/data/aots/tests/gpos_chaining2_lookupflag.tests
new file mode 100644 (file)
index 0000000..8b50e14
--- /dev/null
@@ -0,0 +1 @@
+#../fonts/gpos_chaining2_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20@1500,0|90@3000,0|21@4500,0|91@6000,0|22@7500,0|92@9000,0|23@10520,0|93@12000,0|94@13500,0|24@15000,0|90@16500,0|25@18000,0|91@19500,0|26@21000,0|0@22500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_multiple_subrules.tests b/test/shaping/data/aots/tests/gpos_chaining2_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..8ddc8b2
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_chaining2_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|24@7500,0|0@9000,0|20@10500,0|21@12000,0|22@13520,0|23@15000,0|0@16500,0]
+../fonts/gpos_chaining2_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|24@7500,0|0@9000,0|20@10500,0|21@12000,0|22@13520,0|23@15000,0|0@16500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_next_glyph.tests b/test/shaping/data/aots/tests/gpos_chaining2_next_glyph.tests
new file mode 100644 (file)
index 0000000..34170f2
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining2_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6020,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_simple.tests b/test/shaping/data/aots/tests/gpos_chaining2_simple.tests
new file mode 100644 (file)
index 0000000..32fda1b
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gpos_chaining2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|0@10500,0|0@12000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22@1500,0|23@3000,0|24@4500,0|25@6000,0|26@7500,0|0@9000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23@1500,0|24@3000,0|25@4500,0|26@6000,0|0@7500,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|0@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0]
+../fonts/gpos_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016:[0|20@1500,0|21@3000,0|22@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining2_successive.tests b/test/shaping/data/aots/tests/gpos_chaining2_successive.tests
new file mode 100644 (file)
index 0000000..e930863
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining2_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25@1500,0|20@3000,0|21@4520,0|22@6020,0|23@7500,0|24@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining3_boundary.tests b/test/shaping/data/aots/tests/gpos_chaining3_boundary.tests
new file mode 100644 (file)
index 0000000..f74dedf
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gpos_chaining3_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining3_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining3_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining3_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining3_lookupflag.tests b/test/shaping/data/aots/tests/gpos_chaining3_lookupflag.tests
new file mode 100644 (file)
index 0000000..0165fb5
--- /dev/null
@@ -0,0 +1 @@
+#../fonts/gpos_chaining3_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20@1500,0|90@3000,0|21@4500,0|91@6000,0|22@7500,0|92@9000,0|23@10520,0|93@12000,0|94@13500,0|24@15000,0|90@16500,0|25@18000,0|91@19500,0|26@21000,0|0@22500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining3_next_glyph.tests b/test/shaping/data/aots/tests/gpos_chaining3_next_glyph.tests
new file mode 100644 (file)
index 0000000..614bc2e
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining3_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0016,U+0015,U+0016,U+0015,U+0016,U+0015,U+0000:[0|22@1500,0|21@3020,0|22@4500,0|21@6020,0|22@7500,0|21@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining3_simple.tests b/test/shaping/data/aots/tests/gpos_chaining3_simple.tests
new file mode 100644 (file)
index 0000000..f5977c2
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gpos_chaining3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4520,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|0@10500,0|0@12000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0@1500,0|21@3000,0|22@4500,0|23@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22@1500,0|23@3000,0|24@4500,0|25@6000,0|26@7500,0|0@9000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23@1500,0|24@3000,0|25@4500,0|26@6000,0|0@7500,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|0@6000,0|24@7500,0|25@9000,0|26@10500,0|0@12000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20@1500,0|21@3000,0|22@4500,0|23@6000,0]
+../fonts/gpos_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016:[0|20@1500,0|21@3000,0|22@4500,0]
diff --git a/test/shaping/data/aots/tests/gpos_chaining3_successive.tests b/test/shaping/data/aots/tests/gpos_chaining3_successive.tests
new file mode 100644 (file)
index 0000000..fa5a50c
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_chaining3_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25@1500,0|20@3000,0|21@4520,0|22@6020,0|23@7500,0|24@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_boundary.tests b/test/shaping/data/aots/tests/gpos_context1_boundary.tests
new file mode 100644 (file)
index 0000000..1db8fef
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context1_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1500,0|20@3000,0|20@4500,0|20@6000,0|20@7500,0|0@9000,0]
+../fonts/gpos_context1_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3020,0|20@4520,0|20@6020,0|20@7520,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_expansion.tests b/test/shaping/data/aots/tests/gpos_context1_expansion.tests
new file mode 100644 (file)
index 0000000..2fc54d5
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context1_expansion_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|0@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_lookupflag.tests b/test/shaping/data/aots/tests/gpos_context1_lookupflag.tests
new file mode 100644 (file)
index 0000000..9e8fcd6
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos_context1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1520,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9020,0|0@10500,0]
+#../fonts/gpos_context1_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1500,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_multiple_subrules.tests b/test/shaping/data/aots/tests/gpos_context1_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..b994f04
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context1_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20@1520,0|21@3000,0|22@4500,0|0@6000,0|20@7500,0|21@9020,0|0@10500,0]
+../fonts/gpos_context1_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|0@6000,0|20@7500,0|21@9020,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_next_glyph.tests b/test/shaping/data/aots/tests/gpos_context1_next_glyph.tests
new file mode 100644 (file)
index 0000000..e67d635
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context1_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3000,0|20@4520,0|20@6000,0|20@7500,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_simple.tests b/test/shaping/data/aots/tests/gpos_context1_simple.tests
new file mode 100644 (file)
index 0000000..4a88e0a
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/gpos_context1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1520,0|21@3020,0|22@4520,0|0@6000,0]
+../fonts/gpos_context1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000:[0|20@1500,0|0@3000,0|20@4500,0|21@6000,0|0@7500,0]
+../fonts/gpos_context1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1500,0|20@3020,0|20@4500,0|20@6000,0|20@7500,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context1_successive.tests b/test/shaping/data/aots/tests/gpos_context1_successive.tests
new file mode 100644 (file)
index 0000000..172d350
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context1_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_boundary.tests b/test/shaping/data/aots/tests/gpos_context2_boundary.tests
new file mode 100644 (file)
index 0000000..ef63fbb
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context2_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1500,0|20@3000,0|20@4500,0|20@6000,0|20@7500,0|0@9000,0]
+../fonts/gpos_context2_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3020,0|20@4520,0|20@6020,0|20@7520,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_classes.tests b/test/shaping/data/aots/tests/gpos_context2_classes.tests
new file mode 100644 (file)
index 0000000..5a3d008
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context2_classes_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+001A,U+001C,U+0018,U+0000,U+0015,U+001B,U+001A,U+0018,U+0000,U+0016,U+001B,U+001A,U+0018:[0|20@1500,0|26@3020,0|28@4500,0|24@6000,0|0@7500,0|21@9000,0|27@10520,0|26@12000,0|24@13500,0|0@15000,0|22@16500,0|27@18000,0|26@19500,0|24@21000,0]
+../fonts/gpos_context2_classes_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0016,U+001B,U+001A,U+0018,U+0000,U+0018,U+0018,U+001D,U+0016,U+0000,U+0016,U+001B,U+001A,U+0018:[0|22@1500,0|27@3020,0|26@4500,0|24@6000,0|0@7500,0|24@9000,0|24@10500,0|29@12020,0|22@13500,0|0@15000,0|22@16500,0|27@18020,0|26@19500,0|24@21000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_expansion.tests b/test/shaping/data/aots/tests/gpos_context2_expansion.tests
new file mode 100644 (file)
index 0000000..67ed978
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context2_expansion_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1500,0|21@3000,0|22@4500,0|0@6000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_lookupflag.tests b/test/shaping/data/aots/tests/gpos_context2_lookupflag.tests
new file mode 100644 (file)
index 0000000..f48e825
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos_context2_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1520,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9020,0|0@10500,0]
+#../fonts/gpos_context2_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1500,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_multiple_subrules.tests b/test/shaping/data/aots/tests/gpos_context2_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..4489372
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context2_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20@1520,0|21@3000,0|22@4500,0|0@6000,0|20@7500,0|21@9020,0|0@10500,0]
+../fonts/gpos_context2_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20@1500,0|21@3020,0|22@4500,0|0@6000,0|20@7500,0|21@9020,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_next_glyph.tests b/test/shaping/data/aots/tests/gpos_context2_next_glyph.tests
new file mode 100644 (file)
index 0000000..e736b3b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context2_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3000,0|20@4520,0|20@6000,0|20@7500,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_simple.tests b/test/shaping/data/aots/tests/gpos_context2_simple.tests
new file mode 100644 (file)
index 0000000..edbc0be
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/gpos_context2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1520,0|21@3020,0|22@4520,0|0@6000,0]
+../fonts/gpos_context2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000:[0|20@1500,0|0@3000,0|20@4500,0|21@6000,0|0@7500,0]
+../fonts/gpos_context2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1500,0|20@3020,0|20@4500,0|20@6000,0|20@7500,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context2_successive.tests b/test/shaping/data/aots/tests/gpos_context2_successive.tests
new file mode 100644 (file)
index 0000000..8b098d5
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context2_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context3_boundary.tests b/test/shaping/data/aots/tests/gpos_context3_boundary.tests
new file mode 100644 (file)
index 0000000..de3c057
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context3_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1500,0|20@3000,0|20@4500,0|20@6000,0|20@7500,0|0@9000,0]
+../fonts/gpos_context3_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3020,0|20@4520,0|20@6020,0|20@7520,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context3_lookupflag.tests b/test/shaping/data/aots/tests/gpos_context3_lookupflag.tests
new file mode 100644 (file)
index 0000000..21f851b
--- /dev/null
@@ -0,0 +1,2 @@
+#../fonts/gpos_context3_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1520,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9020,0|0@10500,0]
+#../fonts/gpos_context3_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20@1500,0|90@3000,0|21@4520,0|91@6000,0|92@7500,0|22@9000,0|0@10500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context3_next_glyph.tests b/test/shaping/data/aots/tests/gpos_context3_next_glyph.tests
new file mode 100644 (file)
index 0000000..049b156
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context3_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20@1520,0|20@3000,0|20@4520,0|20@6000,0|20@7500,0|0@9000,0]
diff --git a/test/shaping/data/aots/tests/gpos_context3_simple.tests b/test/shaping/data/aots/tests/gpos_context3_simple.tests
new file mode 100644 (file)
index 0000000..3e544f0
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gpos_context3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1520,0|21@3020,0|22@4520,0|0@6000,0]
+../fonts/gpos_context3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000,U+0014,U+0015,U+0016,U+0000:[0|20@1500,0|0@3000,0|20@4500,0|21@6000,0|0@7500,0|20@9020,0|21@10520,0|22@12020,0|0@13500,0]
diff --git a/test/shaping/data/aots/tests/gpos_context3_successive.tests b/test/shaping/data/aots/tests/gpos_context3_successive.tests
new file mode 100644 (file)
index 0000000..bfcf24a
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gpos_context3_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --ned:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20@1500,0|21@3020,0|22@4520,0|23@6000,0|0@7500,0]
diff --git a/test/shaping/data/aots/tests/gsub1_1_lookupflag.tests b/test/shaping/data/aots/tests/gsub1_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..8865af8
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub1_1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18|24|20|21]
diff --git a/test/shaping/data/aots/tests/gsub1_1_modulo.tests b/test/shaping/data/aots/tests/gsub1_1_modulo.tests
new file mode 100644 (file)
index 0000000..bbfff5e
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub1_1_modulo_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015,U+0016,U+0017,U+0018:[17|18|17|24|23|18|23|24]
diff --git a/test/shaping/data/aots/tests/gsub1_1_simple.tests b/test/shaping/data/aots/tests/gsub1_1_simple.tests
new file mode 100644 (file)
index 0000000..a3a1385
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub1_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|20|21]
diff --git a/test/shaping/data/aots/tests/gsub1_2_lookupflag.tests b/test/shaping/data/aots/tests/gsub1_2_lookupflag.tests
new file mode 100644 (file)
index 0000000..887e047
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub1_2_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|18|19|25|21]
diff --git a/test/shaping/data/aots/tests/gsub1_2_simple.tests b/test/shaping/data/aots/tests/gsub1_2_simple.tests
new file mode 100644 (file)
index 0000000..d657897
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub1_2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|22|19|25|21]
diff --git a/test/shaping/data/aots/tests/gsub2_1_lookupflag.tests b/test/shaping/data/aots/tests/gsub2_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..e28e59c
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub2_1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0011:[17|18|22|23|17]
diff --git a/test/shaping/data/aots/tests/gsub2_1_multiple_sequences.tests b/test/shaping/data/aots/tests/gsub2_1_multiple_sequences.tests
new file mode 100644 (file)
index 0000000..12cbbf6
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub2_1_multiple_sequences_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0011:[17|20|21|22|23|17]
diff --git a/test/shaping/data/aots/tests/gsub2_1_simple.tests b/test/shaping/data/aots/tests/gsub2_1_simple.tests
new file mode 100644 (file)
index 0000000..d1d0969
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub2_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013:[17|20|21|22|19]
+../fonts/gsub2_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0012:[17|20|21|22|19|20|21|22]
diff --git a/test/shaping/data/aots/tests/gsub3_1_lookupflag.tests b/test/shaping/data/aots/tests/gsub3_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..193c5c4
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub3_1_lookupflag_f1.otf:--features="-test[4],test[5],test[6]=2,-test[7]" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0012,U+0012,U+0013,U+0013,U+0013,U+0013,U+0011:[17|18|18|18|19|22|23|19|17]
diff --git a/test/shaping/data/aots/tests/gsub3_1_multiple.tests b/test/shaping/data/aots/tests/gsub3_1_multiple.tests
new file mode 100644 (file)
index 0000000..7b1c032
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub3_1_multiple_f1.otf:--features="-test[1],test[2],test[3]=2,-test[4],-test[5],test[6],test[7]=2,-test[8]" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0012,U+0012,U+0012,U+0013,U+0013,U+0013,U+0013,U+0011:[17|18|20|21|18|19|22|23|19|17]
diff --git a/test/shaping/data/aots/tests/gsub3_1_simple.tests b/test/shaping/data/aots/tests/gsub3_1_simple.tests
new file mode 100644 (file)
index 0000000..b8a28d1
--- /dev/null
@@ -0,0 +1 @@
+#../fonts/gsub3_1_simple_f1.otf:--features="-test[1],test[3],test[5]=2,test[7]=3,-test[9],test[11]" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0011,U+0012,U+0011,U+0012,U+0011,U+0012,U+0011,U+0012,U+0011,U+0012,U+0011:[17|18|17|20|17|21|17|22|17|18|17|20|17]
diff --git a/test/shaping/data/aots/tests/gsub4_1_lookupflag.tests b/test/shaping/data/aots/tests/gsub4_1_lookupflag.tests
new file mode 100644 (file)
index 0000000..c2c5242
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub4_1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0018,U+0012,U+0018,U+0013,U+0018,U+0018,U+0014,U+0018,U+0011,U+0012,U+0013,U+0016,U+0014:[17|24|23|24|24|24|24|17|18|19|22|20]
diff --git a/test/shaping/data/aots/tests/gsub4_1_multiple_ligatures.tests b/test/shaping/data/aots/tests/gsub4_1_multiple_ligatures.tests
new file mode 100644 (file)
index 0000000..33c1a09
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub4_1_multiple_ligatures_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0011,U+0012,U+0013,U+0016,U+0014:[17|23|17|24|22|20]
+../fonts/gsub4_1_multiple_ligatures_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0011,U+0012,U+0013,U+0016,U+0014:[17|24|20|17|24|22|20]
diff --git a/test/shaping/data/aots/tests/gsub4_1_multiple_ligsets.tests b/test/shaping/data/aots/tests/gsub4_1_multiple_ligsets.tests
new file mode 100644 (file)
index 0000000..a63aeed
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub4_1_multiple_ligsets_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0015,U+0014,U+0013,U+0016:[17|23|21|24|22]
diff --git a/test/shaping/data/aots/tests/gsub4_1_simple.tests b/test/shaping/data/aots/tests/gsub4_1_simple.tests
new file mode 100644 (file)
index 0000000..aa4bb4b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub4_1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0011,U+0012,U+0013,U+0016,U+0014:[17|23|17|18|19|22|20]
diff --git a/test/shaping/data/aots/tests/gsub7.tests b/test/shaping/data/aots/tests/gsub7.tests
new file mode 100644 (file)
index 0000000..e95b1c7
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub7_font1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|24|20|21]
+../fonts/gsub7_font2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|29|20|21]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_boundary.tests b/test/shaping/data/aots/tests/gsub_chaining1_boundary.tests
new file mode 100644 (file)
index 0000000..6d99d97
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gsub_chaining1_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|22|23|0]
+../fonts/gsub_chaining1_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining1_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining1_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|62|23|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_lookupflag.tests b/test/shaping/data/aots/tests/gsub_chaining1_lookupflag.tests
new file mode 100644 (file)
index 0000000..7883c0a
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20|90|21|91|22|92|63|93|94|24|90|25|91|26|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_multiple_subrules.tests b/test/shaping/data/aots/tests/gsub_chaining1_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..28a5225
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_chaining1_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|24|0|20|21|62|23|0]
+../fonts/gsub_chaining1_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|62|23|24|0|20|21|62|23|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_next_glyph.tests b/test/shaping/data/aots/tests/gsub_chaining1_next_glyph.tests
new file mode 100644 (file)
index 0000000..82f9d95
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining1_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|62|63|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_simple.tests b/test/shaping/data/aots/tests/gsub_chaining1_simple.tests
new file mode 100644 (file)
index 0000000..23e091f
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gsub_chaining1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|62|23|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20|21|62|23|24|25|26|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20|21|22|23|24|25|0|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20|21|22|23|24|25]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20|21|22|23|24]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0|21|22|23|24|25|26|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22|23|24|25|26|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23|24|25|26|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20|21|22|0|24|25|26|0]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20|21|22|23]
+../fonts/gsub_chaining1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016:[0|20|21|22]
diff --git a/test/shaping/data/aots/tests/gsub_chaining1_successive.tests b/test/shaping/data/aots/tests/gsub_chaining1_successive.tests
new file mode 100644 (file)
index 0000000..ab3cfb1
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining1_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25|20|61|63|24|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_boundary.tests b/test/shaping/data/aots/tests/gsub_chaining2_boundary.tests
new file mode 100644 (file)
index 0000000..b06c620
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gsub_chaining2_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|22|23|0]
+../fonts/gsub_chaining2_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining2_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining2_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|62|23|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_lookupflag.tests b/test/shaping/data/aots/tests/gsub_chaining2_lookupflag.tests
new file mode 100644 (file)
index 0000000..372b343
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining2_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20|90|21|91|22|92|63|93|94|24|90|25|91|26|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_multiple_subrules.tests b/test/shaping/data/aots/tests/gsub_chaining2_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..e2fbb5c
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_chaining2_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|24|0|20|21|62|23|0]
+../fonts/gsub_chaining2_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|62|23|24|0|20|21|62|23|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_next_glyph.tests b/test/shaping/data/aots/tests/gsub_chaining2_next_glyph.tests
new file mode 100644 (file)
index 0000000..84c8252
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining2_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|62|63|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_simple.tests b/test/shaping/data/aots/tests/gsub_chaining2_simple.tests
new file mode 100644 (file)
index 0000000..53fa7e8
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gsub_chaining2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|62|23|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20|21|62|23|24|25|26|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20|21|22|23|24|25|0|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20|21|22|23|24|25]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20|21|22|23|24]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0|21|22|23|24|25|26|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22|23|24|25|26|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23|24|25|26|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20|21|22|0|24|25|26|0]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20|21|22|23]
+../fonts/gsub_chaining2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016:[0|20|21|22]
diff --git a/test/shaping/data/aots/tests/gsub_chaining2_successive.tests b/test/shaping/data/aots/tests/gsub_chaining2_successive.tests
new file mode 100644 (file)
index 0000000..71cbe0d
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining2_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25|20|61|63|24|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining3_boundary.tests b/test/shaping/data/aots/tests/gsub_chaining3_boundary.tests
new file mode 100644 (file)
index 0000000..c01dc4b
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/gsub_chaining3_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|22|23|0]
+../fonts/gsub_chaining3_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining3_boundary_f3.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|22|23|0]
+../fonts/gsub_chaining3_boundary_f4.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|21|62|23|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining3_lookupflag.tests b/test/shaping/data/aots/tests/gsub_chaining3_lookupflag.tests
new file mode 100644 (file)
index 0000000..be2147b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining3_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+0016,U+005C,U+0017,U+005D,U+005E,U+0018,U+005A,U+0019,U+005B,U+001A,U+0000:[0|20|90|21|91|22|92|63|93|94|24|90|25|91|26|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining3_next_glyph.tests b/test/shaping/data/aots/tests/gsub_chaining3_next_glyph.tests
new file mode 100644 (file)
index 0000000..2493c1e
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining3_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0016,U+0015,U+0016,U+0015,U+0016,U+0015,U+0000:[0|22|61|22|61|22|21|0]
diff --git a/test/shaping/data/aots/tests/gsub_chaining3_simple.tests b/test/shaping/data/aots/tests/gsub_chaining3_simple.tests
new file mode 100644 (file)
index 0000000..eb24167
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/gsub_chaining3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|62|23|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|20|21|62|23|24|25|26|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019,U+0000,U+0000:[0|20|21|22|23|24|25|0|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018,U+0019:[0|20|21|22|23|24|25]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0018:[0|20|21|22|23|24]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0000,U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[0|0|21|22|23|24|25|26|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0015,U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[21|22|23|24|25|26|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0016,U+0017,U+0018,U+0019,U+001A,U+0000:[22|23|24|25|26|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0018,U+0019,U+001A,U+0000:[0|20|21|22|0|24|25|26|0]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017:[0|20|21|22|23]
+../fonts/gsub_chaining3_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016:[0|20|21|22]
diff --git a/test/shaping/data/aots/tests/gsub_chaining3_successive.tests b/test/shaping/data/aots/tests/gsub_chaining3_successive.tests
new file mode 100644 (file)
index 0000000..edcade1
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_chaining3_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0019,U+0014,U+0015,U+0016,U+0017,U+0018,U+0000:[0|25|20|61|63|24|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_boundary.tests b/test/shaping/data/aots/tests/gsub_context1_boundary.tests
new file mode 100644 (file)
index 0000000..9b11892
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context1_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20|20|20|20|20|0]
+../fonts/gsub_context1_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|60|60|60|60|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_expansion.tests b/test/shaping/data/aots/tests/gsub_context1_expansion.tests
new file mode 100644 (file)
index 0000000..92714c5
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context1_expansion_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20|61|62|63|22|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_lookupflag.tests b/test/shaping/data/aots/tests/gsub_context1_lookupflag.tests
new file mode 100644 (file)
index 0000000..c5d9760
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context1_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|60|90|61|91|92|62|0]
+../fonts/gsub_context1_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20|90|61|91|92|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_multiple_subrules.tests b/test/shaping/data/aots/tests/gsub_context1_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..febc419
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context1_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|60|21|22|0|20|61|0]
+../fonts/gsub_context1_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20|61|22|0|20|61|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_next_glyph.tests b/test/shaping/data/aots/tests/gsub_context1_next_glyph.tests
new file mode 100644 (file)
index 0000000..12414c3
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context1_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|20|60|20|20|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_simple.tests b/test/shaping/data/aots/tests/gsub_context1_simple.tests
new file mode 100644 (file)
index 0000000..44252ec
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/gsub_context1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000:[0|60|61|62|0]
+../fonts/gsub_context1_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000:[0|20|0|20|21|0]
+../fonts/gsub_context1_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20|60|20|20|20|0]
diff --git a/test/shaping/data/aots/tests/gsub_context1_successive.tests b/test/shaping/data/aots/tests/gsub_context1_successive.tests
new file mode 100644 (file)
index 0000000..e68d6b2
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context1_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|63|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_boundary.tests b/test/shaping/data/aots/tests/gsub_context2_boundary.tests
new file mode 100644 (file)
index 0000000..2054277
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context2_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20|20|20|20|20|0]
+../fonts/gsub_context2_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|60|60|60|60|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_classes.tests b/test/shaping/data/aots/tests/gsub_context2_classes.tests
new file mode 100644 (file)
index 0000000..2e44007
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context2_classes_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+001A,U+001C,U+0018,U+0000,U+0015,U+001B,U+001A,U+0018,U+0000,U+0016,U+001B,U+001A,U+0018:[0|20|66|28|24|0|21|67|26|24|0|22|27|26|24]
+../fonts/gsub_context2_classes_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0016,U+001B,U+001A,U+0018,U+0000,U+0018,U+0018,U+001D,U+0016,U+0000,U+0016,U+001B,U+001A,U+0018:[0|22|67|26|24|0|24|24|69|22|0|22|67|26|24]
diff --git a/test/shaping/data/aots/tests/gsub_context2_expansion.tests b/test/shaping/data/aots/tests/gsub_context2_expansion.tests
new file mode 100644 (file)
index 0000000..af0ce71
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context2_expansion_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000:[0|20|61|62|63|22|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_lookupflag.tests b/test/shaping/data/aots/tests/gsub_context2_lookupflag.tests
new file mode 100644 (file)
index 0000000..ac41949
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context2_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|60|90|61|91|92|62|0]
+../fonts/gsub_context2_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20|90|61|91|92|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_multiple_subrules.tests b/test/shaping/data/aots/tests/gsub_context2_multiple_subrules.tests
new file mode 100644 (file)
index 0000000..75225cd
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context2_multiple_subrules_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|60|21|22|0|20|61|0]
+../fonts/gsub_context2_multiple_subrules_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000,U+0014,U+0015,U+0000:[0|20|61|22|0|20|61|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_next_glyph.tests b/test/shaping/data/aots/tests/gsub_context2_next_glyph.tests
new file mode 100644 (file)
index 0000000..020d05f
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context2_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|20|60|20|20|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_simple.tests b/test/shaping/data/aots/tests/gsub_context2_simple.tests
new file mode 100644 (file)
index 0000000..5863605
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/gsub_context2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000:[0|60|61|62|0]
+../fonts/gsub_context2_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000:[0|20|0|20|21|0]
+../fonts/gsub_context2_simple_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20|60|20|20|20|0]
diff --git a/test/shaping/data/aots/tests/gsub_context2_successive.tests b/test/shaping/data/aots/tests/gsub_context2_successive.tests
new file mode 100644 (file)
index 0000000..9aeeac7
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context2_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|63|0]
diff --git a/test/shaping/data/aots/tests/gsub_context3_boundary.tests b/test/shaping/data/aots/tests/gsub_context3_boundary.tests
new file mode 100644 (file)
index 0000000..8b40afd
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context3_boundary_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|20|20|20|20|20|0]
+../fonts/gsub_context3_boundary_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|60|60|60|60|0]
diff --git a/test/shaping/data/aots/tests/gsub_context3_lookupflag.tests b/test/shaping/data/aots/tests/gsub_context3_lookupflag.tests
new file mode 100644 (file)
index 0000000..03c0647
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context3_lookupflag_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|60|90|61|91|92|62|0]
+../fonts/gsub_context3_lookupflag_f2.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+005A,U+0015,U+005B,U+005C,U+0016,U+0000:[0|20|90|61|91|92|0]
diff --git a/test/shaping/data/aots/tests/gsub_context3_next_glyph.tests b/test/shaping/data/aots/tests/gsub_context3_next_glyph.tests
new file mode 100644 (file)
index 0000000..b28381b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context3_next_glyph_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0014,U+0014,U+0014,U+0014,U+0000:[0|60|20|60|20|20|0]
diff --git a/test/shaping/data/aots/tests/gsub_context3_simple.tests b/test/shaping/data/aots/tests/gsub_context3_simple.tests
new file mode 100644 (file)
index 0000000..ec264ea
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/gsub_context3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0000:[0|60|61|62|0]
+../fonts/gsub_context3_simple_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0000,U+0014,U+0015,U+0000,U+0014,U+0015,U+0016,U+0000:[0|20|0|20|21|0|60|61|62|0]
diff --git a/test/shaping/data/aots/tests/gsub_context3_successive.tests b/test/shaping/data/aots/tests/gsub_context3_successive.tests
new file mode 100644 (file)
index 0000000..b987a61
--- /dev/null
@@ -0,0 +1 @@
+../fonts/gsub_context3_successive_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0000,U+0014,U+0015,U+0016,U+0017,U+0000:[0|20|61|63|0]
diff --git a/test/shaping/data/aots/tests/lookupflag_ignore_attach.tests b/test/shaping/data/aots/tests/lookupflag_ignore_attach.tests
new file mode 100644 (file)
index 0000000..55ae538
--- /dev/null
@@ -0,0 +1,5 @@
+#../fonts/lookupflag_ignore_attach_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+000A,U+000B,U+000D,U+001A,U+000A:[10|15|10]
+#../fonts/lookupflag_ignore_attach_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+000A,U+000B,U+0015,U+000D,U+0016,U+0017,U+001D,U+001A,U+000A:[10|15|21|22|23|29|10]
+#../fonts/lookupflag_ignore_attach_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+000A,U+000B,U+0015,U+000D,U+0016,U+001B,U+001A,U+000A:[10|11|21|13|22|27|26|10]
+#../fonts/lookupflag_ignore_attach_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+000A,U+000B,U+001B,U+000D,U+0016,U+0017,U+001A,U+000A:[10|11|27|13|22|23|26|10]
+#../fonts/lookupflag_ignore_attach_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+000A,U+000B,U+001B,U+000D,U+000E,U+0017,U+001A,U+000A:[10|11|27|13|14|23|26|10]
diff --git a/test/shaping/data/aots/tests/lookupflag_ignore_base.tests b/test/shaping/data/aots/tests/lookupflag_ignore_base.tests
new file mode 100644 (file)
index 0000000..5f0bfdb
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/lookupflag_ignore_base_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0013,U+0014,U+0015:[17|23|21]
+../fonts/lookupflag_ignore_base_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+0018,U+0018,U+0013,U+0019,U+0014,U+0015:[17|23|24|24|25|21]
diff --git a/test/shaping/data/aots/tests/lookupflag_ignore_combination.tests b/test/shaping/data/aots/tests/lookupflag_ignore_combination.tests
new file mode 100644 (file)
index 0000000..d34f16a
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/lookupflag_ignore_combination_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+0013,U+0014,U+0015:[17|23|26|21]
+../fonts/lookupflag_ignore_combination_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+0013,U+0018,U+001E,U+001F,U+0014,U+0015:[17|23|26|24|30|31|21]
+../fonts/lookupflag_ignore_combination_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+0013,U+0018,U+001E,U+0020,U+0014,U+0015:[17|18|26|19|24|30|32|20|21]
diff --git a/test/shaping/data/aots/tests/lookupflag_ignore_ligatures.tests b/test/shaping/data/aots/tests/lookupflag_ignore_ligatures.tests
new file mode 100644 (file)
index 0000000..feb31d8
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/lookupflag_ignore_ligatures_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+001B,U+0013,U+001B,U+0014,U+0015:[17|23|26|27|27|21]
+../fonts/lookupflag_ignore_ligatures_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+0018,U+0013,U+001B,U+0014,U+0015:[17|18|26|24|19|27|20|21]
+../fonts/lookupflag_ignore_ligatures_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001A,U+002A,U+0013,U+001B,U+0014,U+0015:[17|18|26|42|19|27|20|21]
diff --git a/test/shaping/data/aots/tests/lookupflag_ignore_marks.tests b/test/shaping/data/aots/tests/lookupflag_ignore_marks.tests
new file mode 100644 (file)
index 0000000..9626599
--- /dev/null
@@ -0,0 +1 @@
+../fonts/lookupflag_ignore_marks_f1.otf:--features="test" --no-clusters --no-glyph-names --no-positions:U+0011,U+0012,U+001C,U+001D,U+0013,U+001D,U+0014,U+0015:[17|23|28|29|29|21]
index b9e702a..590807b 100644 (file)
@@ -89,29 +89,34 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-TESTS = tests/arabic-fallback-shaping.tests \
+TESTS = tests/aat-trak.tests tests/aat-morx.tests \
+       tests/arabic-fallback-shaping.tests \
        tests/arabic-feature-order.tests \
-       tests/arabic-like-joining.tests tests/arabic-mark-order.tests \
-       tests/arabic-stch.tests tests/automatic-fractions.tests \
-       tests/cluster.tests tests/color-fonts.tests \
+       tests/arabic-like-joining.tests tests/arabic-mark-attach.tests \
+       tests/arabic-mark-order.tests tests/arabic-stch.tests \
+       tests/automatic-fractions.tests tests/cluster.tests \
+       tests/collections.tests tests/color-fonts.tests \
        tests/context-matching.tests tests/cursive-positioning.tests \
-       tests/default-ignorables.tests tests/emoji-flag-tags.tests \
-       tests/fallback-positioning.tests tests/fuzzed.tests \
-       tests/hangul-jamo.tests tests/hyphens.tests \
-       tests/indic-consonant-with-stacker.tests \
+       tests/default-ignorables.tests tests/emoji.tests \
+       tests/fallback-positioning.tests tests/hangul-jamo.tests \
+       tests/hyphens.tests tests/indic-consonant-with-stacker.tests \
        tests/indic-decompose.tests tests/indic-init.tests \
        tests/indic-joiner-candrabindu.tests tests/indic-joiners.tests \
        tests/indic-old-spec.tests tests/indic-pref-blocking.tests \
        tests/indic-script-extensions.tests \
        tests/indic-special-cases.tests tests/indic-syllable.tests \
-       tests/language-tags.tests tests/ligature-id.tests \
+       tests/indic-vowel-letter-spoofing.tests \
+       tests/kern-format2.tests tests/khmer-mark-order.tests \
+       tests/khmer-misc.tests tests/language-tags.tests \
+       tests/ligature-id.tests tests/macos.tests \
        tests/mark-attachment.tests tests/mark-filtering-sets.tests \
        tests/mongolian-variation-selector.tests \
-       tests/myanmar-syllable.tests tests/none-directional.tests \
+       tests/myanmar-syllable.tests tests/myanmar-zawgyi.tests \
+       tests/none-directional.tests tests/rand.tests \
        tests/spaces.tests tests/simple.tests tests/sinhala.tests \
        tests/tibetan-contractions-1.tests \
        tests/tibetan-contractions-2.tests tests/tibetan-vowels.tests \
-       tests/use.tests tests/use-marchen.tests \
+       tests/use.tests tests/use-indic3.tests tests/use-marchen.tests \
        tests/use-syllable.tests tests/variations-rvrn.tests \
        tests/vertical.tests tests/zero-width-marks.tests \
        $(am__EXEEXT_1)
@@ -122,8 +127,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -473,6 +477,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
index ef16fae..0e9a3a2 100644 (file)
@@ -1,18 +1,21 @@
 TESTS = \
+       tests/aat-trak.tests \
+       tests/aat-morx.tests \
        tests/arabic-fallback-shaping.tests \
        tests/arabic-feature-order.tests \
        tests/arabic-like-joining.tests \
+       tests/arabic-mark-attach.tests \
        tests/arabic-mark-order.tests \
        tests/arabic-stch.tests \
        tests/automatic-fractions.tests \
        tests/cluster.tests \
+       tests/collections.tests \
        tests/color-fonts.tests \
        tests/context-matching.tests \
        tests/cursive-positioning.tests \
        tests/default-ignorables.tests \
-       tests/emoji-flag-tags.tests \
+       tests/emoji.tests \
        tests/fallback-positioning.tests \
-       tests/fuzzed.tests \
        tests/hangul-jamo.tests \
        tests/hyphens.tests \
        tests/indic-consonant-with-stacker.tests \
@@ -25,13 +28,20 @@ TESTS = \
        tests/indic-script-extensions.tests \
        tests/indic-special-cases.tests \
        tests/indic-syllable.tests \
+       tests/indic-vowel-letter-spoofing.tests \
+       tests/kern-format2.tests \
+       tests/khmer-mark-order.tests \
+       tests/khmer-misc.tests \
        tests/language-tags.tests \
        tests/ligature-id.tests \
+       tests/macos.tests \
        tests/mark-attachment.tests \
        tests/mark-filtering-sets.tests \
        tests/mongolian-variation-selector.tests \
        tests/myanmar-syllable.tests \
+       tests/myanmar-zawgyi.tests \
        tests/none-directional.tests \
+       tests/rand.tests \
        tests/spaces.tests \
        tests/simple.tests \
        tests/sinhala.tests \
@@ -39,6 +49,7 @@ TESTS = \
        tests/tibetan-contractions-2.tests \
        tests/tibetan-vowels.tests \
        tests/use.tests \
+       tests/use-indic3.tests \
        tests/use-marchen.tests \
        tests/use-syllable.tests \
        tests/variations-rvrn.tests \
diff --git a/test/shaping/data/in-house/fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf b/test/shaping/data/in-house/fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf
new file mode 100644 (file)
index 0000000..ee540f3
Binary files /dev/null and b/test/shaping/data/in-house/fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf differ
diff --git a/test/shaping/data/in-house/fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf b/test/shaping/data/in-house/fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf
new file mode 100644 (file)
index 0000000..383aee6
Binary files /dev/null and b/test/shaping/data/in-house/fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf differ
diff --git a/test/shaping/data/in-house/fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf b/test/shaping/data/in-house/fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf
new file mode 100644 (file)
index 0000000..13c4d8a
Binary files /dev/null and b/test/shaping/data/in-house/fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf differ
diff --git a/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf b/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf
new file mode 100644 (file)
index 0000000..a1fef49
Binary files /dev/null and b/test/shaping/data/in-house/fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf differ
diff --git a/test/shaping/data/in-house/fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf b/test/shaping/data/in-house/fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf
new file mode 100644 (file)
index 0000000..ef94d3f
Binary files /dev/null and b/test/shaping/data/in-house/fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf differ
diff --git a/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf b/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf
new file mode 100644 (file)
index 0000000..3dd30ed
Binary files /dev/null and b/test/shaping/data/in-house/fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf differ
diff --git a/test/shaping/data/in-house/fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf b/test/shaping/data/in-house/fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf
new file mode 100644 (file)
index 0000000..cebd375
Binary files /dev/null and b/test/shaping/data/in-house/fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf differ
diff --git a/test/shaping/data/in-house/fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf b/test/shaping/data/in-house/fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf
new file mode 100644 (file)
index 0000000..63c0c71
Binary files /dev/null and b/test/shaping/data/in-house/fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf differ
diff --git a/test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf b/test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf
new file mode 100644 (file)
index 0000000..7d488a3
Binary files /dev/null and b/test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf differ
diff --git a/test/shaping/data/in-house/fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf b/test/shaping/data/in-house/fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf
new file mode 100644 (file)
index 0000000..274fc08
Binary files /dev/null and b/test/shaping/data/in-house/fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf differ
diff --git a/test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf b/test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf
new file mode 100644 (file)
index 0000000..03166b0
Binary files /dev/null and b/test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf differ
diff --git a/test/shaping/data/in-house/fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf b/test/shaping/data/in-house/fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf
new file mode 100644 (file)
index 0000000..14de6a1
Binary files /dev/null and b/test/shaping/data/in-house/fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf differ
diff --git a/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf b/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf
new file mode 100644 (file)
index 0000000..588ce3b
Binary files /dev/null and b/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf differ
diff --git a/test/shaping/data/in-house/fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf b/test/shaping/data/in-house/fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf
new file mode 100644 (file)
index 0000000..a6f1c9d
Binary files /dev/null and b/test/shaping/data/in-house/fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf differ
diff --git a/test/shaping/data/in-house/fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf b/test/shaping/data/in-house/fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf
new file mode 100644 (file)
index 0000000..1328e13
Binary files /dev/null and b/test/shaping/data/in-house/fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf differ
diff --git a/test/shaping/data/in-house/fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf b/test/shaping/data/in-house/fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf
new file mode 100644 (file)
index 0000000..c3e4167
Binary files /dev/null and b/test/shaping/data/in-house/fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf differ
diff --git a/test/shaping/data/in-house/fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf b/test/shaping/data/in-house/fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf
new file mode 100644 (file)
index 0000000..ffdddf3
Binary files /dev/null and b/test/shaping/data/in-house/fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf differ
diff --git a/test/shaping/data/in-house/fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf b/test/shaping/data/in-house/fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf
new file mode 100644 (file)
index 0000000..e8512bb
Binary files /dev/null and b/test/shaping/data/in-house/fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf differ
diff --git a/test/shaping/data/in-house/fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf b/test/shaping/data/in-house/fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf
new file mode 100644 (file)
index 0000000..5a47a39
Binary files /dev/null and b/test/shaping/data/in-house/fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf differ
diff --git a/test/shaping/data/in-house/fonts/881642af1667ae30a54e58de8be904566d00508f.ttf b/test/shaping/data/in-house/fonts/881642af1667ae30a54e58de8be904566d00508f.ttf
new file mode 100644 (file)
index 0000000..a749cdf
Binary files /dev/null and b/test/shaping/data/in-house/fonts/881642af1667ae30a54e58de8be904566d00508f.ttf differ
diff --git a/test/shaping/data/in-house/fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf b/test/shaping/data/in-house/fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf
new file mode 100644 (file)
index 0000000..f1b84a4
Binary files /dev/null and b/test/shaping/data/in-house/fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf differ
diff --git a/test/shaping/data/in-house/fonts/9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf b/test/shaping/data/in-house/fonts/9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf
new file mode 100644 (file)
index 0000000..1841cf3
Binary files /dev/null and b/test/shaping/data/in-house/fonts/9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf differ
diff --git a/test/shaping/data/in-house/fonts/DFONT.dfont b/test/shaping/data/in-house/fonts/DFONT.dfont
new file mode 100644 (file)
index 0000000..a6ea700
Binary files /dev/null and b/test/shaping/data/in-house/fonts/DFONT.dfont differ
diff --git a/test/shaping/data/in-house/fonts/MORXTwentyeight.ttf b/test/shaping/data/in-house/fonts/MORXTwentyeight.ttf
new file mode 100644 (file)
index 0000000..edabb43
Binary files /dev/null and b/test/shaping/data/in-house/fonts/MORXTwentyeight.ttf differ
diff --git a/test/shaping/data/in-house/fonts/TRAK.ttf b/test/shaping/data/in-house/fonts/TRAK.ttf
new file mode 100644 (file)
index 0000000..07ae3af
Binary files /dev/null and b/test/shaping/data/in-house/fonts/TRAK.ttf differ
diff --git a/test/shaping/data/in-house/fonts/TTC.ttc b/test/shaping/data/in-house/fonts/TTC.ttc
new file mode 100644 (file)
index 0000000..a21fe89
Binary files /dev/null and b/test/shaping/data/in-house/fonts/TTC.ttc differ
diff --git a/test/shaping/data/in-house/fonts/ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf b/test/shaping/data/in-house/fonts/ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf
new file mode 100644 (file)
index 0000000..a64ecea
Binary files /dev/null and b/test/shaping/data/in-house/fonts/ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf differ
diff --git a/test/shaping/data/in-house/fonts/af85624080af5627fb050f570d148a62f04fda74.ttf b/test/shaping/data/in-house/fonts/af85624080af5627fb050f570d148a62f04fda74.ttf
new file mode 100644 (file)
index 0000000..9cd40d4
Binary files /dev/null and b/test/shaping/data/in-house/fonts/af85624080af5627fb050f570d148a62f04fda74.ttf differ
diff --git a/test/shaping/data/in-house/fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf b/test/shaping/data/in-house/fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf
new file mode 100644 (file)
index 0000000..a9dc202
Binary files /dev/null and b/test/shaping/data/in-house/fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf differ
diff --git a/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf b/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf
new file mode 100644 (file)
index 0000000..ca23ef8
Binary files /dev/null and b/test/shaping/data/in-house/fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf differ
diff --git a/test/shaping/data/in-house/fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf b/test/shaping/data/in-house/fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf
deleted file mode 100644 (file)
index fba200f..0000000
Binary files a/test/shaping/data/in-house/fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf and /dev/null differ
diff --git a/test/shaping/data/in-house/fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf b/test/shaping/data/in-house/fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf
new file mode 100644 (file)
index 0000000..dbd928a
Binary files /dev/null and b/test/shaping/data/in-house/fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf differ
diff --git a/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf b/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf
new file mode 100644 (file)
index 0000000..4d3e11d
Binary files /dev/null and b/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf differ
diff --git a/test/shaping/data/in-house/fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf b/test/shaping/data/in-house/fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf
new file mode 100644 (file)
index 0000000..b1605c4
Binary files /dev/null and b/test/shaping/data/in-house/fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf differ
diff --git a/test/shaping/data/in-house/tests/aat-morx.tests b/test/shaping/data/in-house/tests/aat-morx.tests
new file mode 100644 (file)
index 0000000..27f5bcc
--- /dev/null
@@ -0,0 +1 @@
+../fonts/MORXTwentyeight.ttf::U+0041,U+0078,U+0045,U+0079,U+0044,U+0079,U+0079:[A_E_D=0+1394|x=0+529|y=0+510|y=5+510|y=6+510]
diff --git a/test/shaping/data/in-house/tests/aat-trak.tests b/test/shaping/data/in-house/tests/aat-trak.tests
new file mode 100644 (file)
index 0000000..4bbe729
--- /dev/null
@@ -0,0 +1,11 @@
+../fonts/TRAK.ttf::U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
+../fonts/TRAK.ttf:--font-ptem=.5:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200]
+../fonts/TRAK.ttf:--font-ptem=1:U+0041,U+0042,U+0043:[A.alt=0@100,0+1200|B=1@100,0+1200|C.alt=2@100,0+1200]
+../fonts/TRAK.ttf:--font-ptem=2:U+0041,U+0042,U+0043:[A.alt=0@93,0+1187|B=1@93,0+1187|C.alt=2@93,0+1187]
+../fonts/TRAK.ttf:--font-ptem=9:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
+../fonts/TRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-12,0+976|B=1@-12,0+976|C.alt=2@-12,0+976]
+../fonts/TRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900]
+../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786]
+../fonts/TRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786]
+../fonts/TRAK.ttf:--font-ptem=144 --features=-trak:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
+../fonts/TRAK.ttf:--font-ptem=144 --features=-trak[1;3]:U+0041,U+0042,U+0043,U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1+1000|C.alt=2+1000|A.alt=3@-107,0+786|B=4@-107,0+786|C.alt=5@-107,0+786]
index 274829c..8b7ced0 100644 (file)
@@ -1 +1 @@
-../fonts/df768b9c257e0c9c35786c47cae15c46571d56be.ttf::U+0633,U+064F,U+0644,U+064E,U+0651,U+0627,U+0651,U+0650,U+0645,U+062A,U+06CC:[uni06CC.fina=10+1655|uni062A.medi=9+868|uni0645.init=8+1098|uni0650=2@221,0+0|uni0651=2@260,736+0|uni064E=2@935,1259+0|uni0651=2@974,736+0|uni06440627.fina=2+1470|uni064F=0@558,-10+0|uni0633.init=0+1585]
+../fonts/df768b9c257e0c9c35786c47cae15c46571d56be.ttf::U+0633,U+064F,U+0644,U+064E,U+0651,U+0627,U+0651,U+0650,U+0645,U+062A,U+06CC:[uni06CC.fina=10+1655|uni062A.medi=9+868|uni0645.init=8+1098|uni0650=2@148,0+0|uni0651=2@187,736+0|uni064E=2@883,1259+0|uni0651=2@922,736+0|uni06440627.fina=2+1470|uni064F=0@629,-10+0|uni0633.init=0+1585]
diff --git a/test/shaping/data/in-house/tests/arabic-mark-attach.tests b/test/shaping/data/in-house/tests/arabic-mark-attach.tests
new file mode 100644 (file)
index 0000000..a577e51
--- /dev/null
@@ -0,0 +1 @@
+../fonts/641ca9d7808b01cafa9a666c13811c9b56eb9c52.ttf::U+064A,U+0633,U+06E1,U+200D,U+0654,U+064E,U+0644:[afii57444.zz04=6+1091|afii57454=1@75,925+0|uni0654=1+0|space=1+0|uni06E1=1@950,1115+0|afii57427.zz03_calt=1+1847|afii57450.zz21=0+345]
index fd0a0fe..928843f 100644 (file)
@@ -1,2 +1,2 @@
-../fonts/4fac3929fc3332834e93673780ec0fe94342d193.ttf:--cluster-level=2:U+0078,U+030A,U+0058,U+030A:[gid2=0+1083|gid3=1@-1131,-8+0|gid1=2+1200|gid3=3@-1190,349+0]
+../fonts/4fac3929fc3332834e93673780ec0fe94342d193.ttf:--cluster-level=2:U+0078,U+030A,U+0058,U+030A:[gid2=0+1083|gid3=1@-1132,-8+0|gid1=2+1200|gid3=3@-1190,349+0]
 ../fonts/43ef465752be9af900745f72fe29cb853a1401a5.ttf:--cluster-level=1:U+05D4,U+05B7,U+05E9,U+05BC,U+05C1,U+05B8,U+05DE,U+05B4,U+05DD:[uni05DD=8+1359|uni05B4=7@111,0+0|uni05DE=6+1391|uni05B8=5+0|uni05BC=3+0|uni05C1=3+0|uni05E9=2+1451|uni05B7=1@28,0+0|uni05D4=0+1338]
diff --git a/test/shaping/data/in-house/tests/collections.tests b/test/shaping/data/in-house/tests/collections.tests
new file mode 100644 (file)
index 0000000..07dac9d
--- /dev/null
@@ -0,0 +1,6 @@
+../fonts/DFONT.dfont:--face-index=0 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
+../fonts/DFONT.dfont:--face-index=1 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]
+../fonts/DFONT.dfont:--face-index=2 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]
+../fonts/TTC.ttc:--face-index=0 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
+../fonts/TTC.ttc:--face-index=1 --font-funcs=ot:U+2026,U+0020,U+002E:[ellipsis=0+723|space=1+250|period=2+241]
+../fonts/TTC.ttc:--face-index=2 --font-funcs=ot:U+2026,U+0020,U+002E:[gid0=0+1000|gid0=1+1000|gid0=2+1000]
index e7311bc..b325d78 100644 (file)
@@ -1 +1 @@
-../fonts/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf:--font-funcs=ot --show-extents:U+1F42F:[gid1=0+2963<0,2178,2963,-2788>]
+../fonts/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf:--font-funcs=ot --show-extents:U+1F42F:[gid1=0+2963<0,2179,2963,-2789>]
index 74d283d..15a1ffc 100644 (file)
@@ -2,3 +2,4 @@
 ../fonts/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf::U+0643,U+0645,U+0645,U+062B,U+0644:[gid8=4+738|gid5=3@441,1197+0|gid6=3@0,432+405|gid9=2@0,477+500|gid9=1@0,577+452|gid10=0@20,1177+207]
 #../fonts/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf::U+0B1F,U+0B4D,U+0B1A,U+0B4D,U+0B1A:[ttaorya=0+1307|casubscriptorya=0@-242,104+-231|casubscriptnarroworya=0@20,104+507]
 ../fonts/07f054357ff8638bac3711b422a1e31180bba863.ttf:--font-funcs=ot --no-glyph-names:U+0606,U+06E1:[2=0@40,502+0|1=0+1000]
+../fonts/9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf::U+16F0A,U+16F57,U+16F8F:[u16F0A=0+422|u16F57=0@0,209+338|u16F8F=0+0]
diff --git a/test/shaping/data/in-house/tests/emoji-flag-tags.tests b/test/shaping/data/in-house/tests/emoji-flag-tags.tests
deleted file mode 100644 (file)
index 189de55..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-../fonts/53374c7ca3657be37efde7ed02ae34229a56ae1f.ttf::U+1F3F4,U+E0055,U+E0053,U+E0064,U+E0065,U+E007F:[u1F3F4=0+2126|space=1+0|space=2+0|space=3+0|space=4+0|space=5+0]
-../fonts/53374c7ca3657be37efde7ed02ae34229a56ae1f.ttf::U+1F3F4,U+E0064,U+E0065,U+E007F:[de=0+3200]
diff --git a/test/shaping/data/in-house/tests/emoji.tests b/test/shaping/data/in-house/tests/emoji.tests
new file mode 100644 (file)
index 0000000..7ee01f3
--- /dev/null
@@ -0,0 +1,5 @@
+../fonts/53374c7ca3657be37efde7ed02ae34229a56ae1f.ttf::U+1F3F4,U+E0055,U+E0053,U+E0064,U+E0065,U+E007F:[u1F3F4=0+2126|space=0+0|space=0+0|space=0+0|space=0+0|space=0+0]
+../fonts/53374c7ca3657be37efde7ed02ae34229a56ae1f.ttf::U+1F3F4,U+E0064,U+E0065,U+E007F:[de=0+3200]
+../fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf:--font-funcs=ot --direction=l:U+1F481,U+1F3FB,U+200D,U+2642,U+FE0F:[gid7=0+2550]
+../fonts/3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf:--font-funcs=ot --direction=r:U+1F481,U+1F3FB,U+200D,U+2642,U+FE0F:[gid7=0+2550]
+../fonts/8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf::U+1F3F4,U+E0067,U+E0062,U+E0077,U+E006C,U+E0073,U+E007F:[.notdef=0+1229|space=0+0|space=0+0|space=0+0|space=0+0|space=0+0|space=0+0]
index 5047d84..0ffee50 100644 (file)
@@ -1,2 +1,2 @@
-../fonts/8228d035fcd65d62ec9728fb34f42c63be93a5d3.ttf::U+0078,U+0301,U+0058,U+0301:[x=0+1030|acutecomb=0@-21,-27+0|X=2+1295|acutecomb=2@-147,320+0]
-../fonts/856ff9562451293cbeff6f396d4e3877c4f0a436.ttf::U+0061,U+035C,U+0062:[uni0061=0+512|uni035C=0@-64,-128+0|uni0062=2+512]
+../fonts/8228d035fcd65d62ec9728fb34f42c63be93a5d3.ttf::U+0078,U+0301,U+0058,U+0301:[x=0+1030|acutecomb=0@-19,-27+0|X=2+1295|acutecomb=2@-151,320+0]
+../fonts/856ff9562451293cbeff6f396d4e3877c4f0a436.ttf::U+0061,U+035C,U+0062:[uni0061=0+512|uni035C=0@0,-128+0|uni0062=2+512]
diff --git a/test/shaping/data/in-house/tests/fuzzed.tests b/test/shaping/data/in-house/tests/fuzzed.tests
deleted file mode 100644 (file)
index 43a1933..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-../fonts/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/641bd9db850193064d17575053ae2bf8ec149ddc.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf:--font-funcs=ot:U+0041:[gid0=0+4352]
-../fonts/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf:--font-funcs=ot:U+0041:[gid0=0+1024]
-../fonts/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf:--font-funcs=ot:U+0041:[gid0=0+1000|gid1=0+1000|gid8=0+1000|gid3=0+1000|gid0=0+1000|gid1=0+1000|gid1=0+1000|gid8=0+1000|gid3=0+1000|gid0=0+1000|gid1=0+1000|gid8=0+1000|gid3=0+1000|gid0=0+1000|gid1=0+1000|gid1=0+1000]
-../fonts/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/3511ff5c1647150595846ac414c595cccac34f18.ttf:--font-funcs=ot --no-positions --no-clusters --no-glyph-names:U+0041:[0|512|15104|11004|3408|18244|17872|17961|0|992|15616|0|14151|20559|20992|5440|256|0|10|8960|256|1024|1490|0|768|4096|256|2216|0|256|256|0|768|10752|11004|3408|18244|17734|53248|256|0|512|14848|10793|57344|768|18227|20285|20480|0|256|0|810|0|11004|3408|18244|17734|53289|57344|768|15667|71|0|20559|21248|256|0|2816|2776|0|51516|0|32|26209|28005|65249|29690|0|51548|0|2454|28783|29556|1291|3458|80|0|2804|210|28786|25968|45763|50546|0|59136|0|38144|256|0|2560|30208|52224|580|17996|21504|6734|108|116|24846|1024|0|255|65280|256|0|8704|1345|23109|8192|10823|21076|8192|12877|20300|8192|6738|20301|8192|16980|21067|8251|18944|255|65280|15360|256|255|65280|256|768|255|65280|256|768|255|65280|256|1024|12|65280|256|1280|255|65280|256|1536|1899|25970|110|11264|27502|29285|12907|25974|28160|14443|25970|28288|3|118|18259|21826|45716|46369|0|0|1|16|17|256|4|16|18244|17734|28|12|0|284|0|28|18256|20307|45114|47616|226|10296|0|57927|1|0|0|21248|5440|256|0|10|768|256|1024|512|0|297|16|24833|28774|10794|2304|29|32|42|64515|42|42|64525|20551|17477|18128|10720|3|61|3408|18244|17734|53289|57344|768|15616|512|55|10576|20307|0|255|56063|53504|42|42|64525|12288|18176|80|20307|1|0|62]
-../fonts/fab39d60d758cb586db5a504f218442cd1395725.ttf:--font-funcs=ot:U+0041,U+0041:[gid0=0+1000|gid0=1+1000]
-../fonts/205edd09bd3d141cc9580f650109556cc28b22cb.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/217a934cfe15c548b572c203dceb2befdf026462.ttf:--font-funcs=ot:U+0061,U+0061,U+0061:[]
-../fonts/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf:--font-funcs=ot:U+FFFD,U+E0100,U+FFFD,U+E0010:[]
-../fonts/a34a9191d9376bda419836effeef7e75c1386016.ttf:--font-funcs=ot:U+0041:[]
-../fonts/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf:--font-funcs=ot:U+0041:[gid0=0+1229]
-../fonts/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/243798dd281c1c77c065958e1ff467420faa9bde.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/dd9f0c7c7c36f75a18be0cab1cddf8f3ab0f366b.ttf:--font-funcs=ot --no-positions --no-clusters --no-glyph-names:U+0041:[0|0|2|0|0|2|0|0|2|0|0|2|0|0|2|0|0|2|0|0|0|2|0|0|0|2|0|0|2|0|0|2|0|0|2|0|0|2|0|0|0|2|0|0|2|0|0|2|0|0|2|0]
-../fonts/ef2511f215aa3ca847cbfffbf861793b42170875.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/9d8a94a67932a3ab75a596fc8b5c6d0392ca9e49.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/bbf4a308c402f0678c3e82844892a4da2ebe598f.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
-../fonts/233c1e252e737ca79e03a9fd56b71aaa4a230f2b.ttf:--font-funcs=ot:U+0041:[gid0=0+1000]
index 87b3603..6b75137 100644 (file)
@@ -1,2 +1,2 @@
 ../fonts/5028afb650b1bb718ed2131e872fbcce57828fff.ttf::U+0B13,U+200D,U+0B01:[omorya=0+1450]
-../fonts/5028afb650b1bb718ed2131e872fbcce57828fff.ttf::U+0B13,U+200C,U+0B01:[oorya=0+1309|space=0+0|candrabinduorya=0+0]
+../fonts/5028afb650b1bb718ed2131e872fbcce57828fff.ttf::U+0B13,U+200C,U+0B01:[oorya=0+1309|space=1+0|candrabinduorya=1+0]
index 57107d5..80e392c 100644 (file)
@@ -1,2 +1,6 @@
-../fonts/f443753e8ffe8e8aae606cfba158e00334b6efb1.ttf::U+179A,U+1784,U+17D2,U+179F,U+200C,U+17CA,U+17B8,U+0020:[uni179a=0+775|uni1784=1+1550|uni179f.sub=1+775|space=1+0|uni17ca=1+0|uni17b8=1@0,300+0|space=7+600]
+../fonts/f443753e8ffe8e8aae606cfba158e00334b6efb1.ttf::U+179A,U+1784,U+17D2,U+179F,U+200C,U+17CA,U+17B8,U+0020:[uni179a=0+775|uni1784=1+1550|uni179f.sub=1+775|space=4+0|uni17ca=4+0|uni17b8=4@0,300+0|space=7+600]
 ../fonts/f443753e8ffe8e8aae606cfba158e00334b6efb1.ttf::U+179A,U+1784,U+17D2,U+179F,U+17CA,U+17B8:[uni179a=0+775|uni1784=1+1550|uni179f.sub=1+775|uni17bb=1@-75,-700+0|uni17b8=1+0]
+../fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf:--font-funcs=ft:U+091F,U+094D,U+200C,U+092F,U+093F:[uni091F=0+876|uni094D=0@4,0+0|space=2+0|uni093F.750=3+397|uni092F=3+924]
+../fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf:--font-funcs=ft:U+091F,U+094D,U+200D,U+092F,U+093F:[uni093F=0+398|uni091F=0+876|uni094D=0@4,0+0|space=0+0|uni092F=0+924]
+../fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf:--font-funcs=ft:U+091F,U+094D,U+200D,U+091F,U+094D,U+200C,U+091F,U+094D,U+200D,U+092F,U+093F:[uni091F=0+876|uni094D=0@4,0+0|space=0+0|uni091F=3+876|uni094D=3@4,0+0|space=5+0|uni093F=6+398|uni091F=6+876|uni094D=6@4,0+0|space=6+0|uni092F=6+924]
+../fonts/8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf:--font-funcs=ft:U+091F,U+094D,U+200D,U+091F,U+094D,U+200D,U+091F,U+094D,U+200D,U+092F,U+093F:[uni093F=0+398|uni091F=0+876|uni094D=0@4,0+0|space=0+0|uni091F=0+876|uni094D=0@4,0+0|space=0+0|uni091F=0+876|uni094D=0@4,0+0|space=0+0|uni092F=0+924]
index cd56319..eb967ad 100644 (file)
@@ -1,2 +1,4 @@
 ../fonts/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf::U+0C9A,U+0CCD,U+0C9A,U+0CCD:[U0C9A_U0CCD.haln=0+1066|U0C9A_0CCD.blwf=0+0]
 ../fonts/270b89df543a7e48e206a2d830c0e10e5265c630.ttf::U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D:[glyph201=0+1183|U0D4D=0+0]
+../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+094D,U+0020:[Tra=0+550|virAma=0@-73,-110+0|space=4+500]
+../fonts/b722a7d09e60421f3efbc706ad348ab47b88567b.ttf::U+091F,U+094D,U+0930,U+0942:[Tra=0+550|UT=0@42,-150+0]
diff --git a/test/shaping/data/in-house/tests/indic-vowel-letter-spoofing.tests b/test/shaping/data/in-house/tests/indic-vowel-letter-spoofing.tests
new file mode 100644 (file)
index 0000000..f8305a3
--- /dev/null
@@ -0,0 +1,53 @@
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0904,U+0020,U+0905,U+0946:[ashortdeva=0+764|space=1+260|adeva=2+764|uni25CC=2+510|eshortvowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0906,U+0020,U+0905,U+093E:[aadeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|aavowelsigndeva=2+259]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0908,U+0020,U+0930,U+094D,U+0907:[iideva=0+491|space=1+260|uni25CC=2+510|rephdeva=2+0|ideva=2+491]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+090A,U+0020,U+0909,U+0941:[uudeva=0+765|space=1+260|udeva=2+548|uni25CC=2+510|uvowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+090D,U+0020,U+090F,U+0945:[ecandradeva=0+553|space=1+260|edeva=2+553|uni25CC=2+510|ecandravowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+090E,U+0020,U+090F,U+0946:[eshortdeva=0+553|space=1+260|edeva=2+553|uni25CC=2+510|eshortvowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0910,U+0020,U+090F,U+0947:[aideva=0+553|space=1+260|edeva=2+553|uni25CC=2+510|evowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0911,U+0020,U+0905,U+0949,U+0020,U+0906,U+0945:[ocandradeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|ocandravowelsigndeva=2+259|space=4+260|aadeva=5+1023|uni25CC=5+510|ecandravowelsigndeva=5+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0912,U+0020,U+0905,U+094A,U+0020,U+0906,U+0946:[oshortdeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|oshortvowelsigndeva=2+259|space=4+260|aadeva=5+1023|uni25CC=5+510|eshortvowelsigndeva=5+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0913,U+0020,U+0905,U+094B,U+0020,U+0906,U+0947:[odeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|ovowelsigndeva=2+259|space=4+260|aadeva=5+1023|uni25CC=5+510|evowelsigndeva=5+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0914,U+0020,U+0905,U+094C,U+0020,U+0906,U+0948:[audeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|auvowelsigndeva=2+259|space=4+260|aadeva=5+1023|uni25CC=5+510|aivowelsigndeva=5+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0972,U+0020,U+0905,U+0945:[acandradeva=0+764|space=1+260|adeva=2+764|uni25CC=2+510|ecandravowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0973,U+0020,U+0905,U+093A:[oedeva=0+764|space=1+260|adeva=2+764|uni25CC=2+510|oevowelsigndeva=2+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0974,U+0020,U+0905,U+093B,U+0020,U+0906,U+093A:[ooedeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|ooevowelsigndeva=2+259|space=4+260|aadeva=5+1023|uni25CC=5+510|oevowelsigndeva=5+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0975,U+0020,U+0905,U+094F:[awdeva=0+1023|space=1+260|adeva=2+764|uni25CC=2+510|awvowelsigndeva=2+259]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0976,U+0020,U+0905,U+0956:[uedeva=0+764|space=1+260|adeva=2+764|uni25CC=2+510|uevowelsigndeva=2@50,0+0]
+../fonts/1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf::U+0977,U+0020,U+0905,U+0957:[uuedeva=0+764|space=1+260|adeva=2+764|uni25CC=2+510|uuevowelsigndeva=2@50,0+0]
+../fonts/881642af1667ae30a54e58de8be904566d00508f.ttf::U+0986,U+0020,U+0985,U+09BE:[aabeng=0+1158|space=1+260|abeng=2+893|uni25CC=2+510|aavowelsignbeng=2+266]
+../fonts/881642af1667ae30a54e58de8be904566d00508f.ttf::U+09E0,U+0020,U+098B,U+09C3:[rrvocalicbeng=0+853|space=1+260|rvocalicbeng=2+853|uni25CC=2+510|rvocalicvowelsignbeng=2+0]
+../fonts/881642af1667ae30a54e58de8be904566d00508f.ttf::U+09E1,U+0020,U+098C,U+09E2:[llvocalicbeng=0+639|space=1+260|lvocalicbeng=2+639|uni25CC=2+510|lvocalicvowelsignbeng=2+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A06,U+0020,U+0A05,U+0A3E:[aaguru=0+2001|space=1+532|aguru=2+1520|uni25CC=2+1044|aamatraguru=2+481]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A07,U+0020,U+0A72,U+0A3F:[iguru=0+1671|space=1+532|iriguru=2+1141|imatraguru=2+530|uni25CC=2+1044]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A08,U+0020,U+0A72,U+0A40:[iiguru=0+1671|space=1+532|iriguru=2+1141|uni25CC=2+1044|iimatraguru=2+530]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A09,U+0020,U+0A73,U+0A41:[uguru=0+1356|space=1+532|uraguru=2+1356|uni25CC=2+1044|umatraguru=2@102,0+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A0A,U+0020,U+0A73,U+0A42:[uuguru=0+1356|space=1+532|uraguru=2+1356|uni25CC=2+1044|uumatraguru=2@102,0+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A0F,U+0020,U+0A72,U+0A47:[eeguru=0+1141|space=1+532|iriguru=2+1141|uni25CC=2+1044|eematraguru=2+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A10,U+0020,U+0A05,U+0A48:[aiguru=0+1520|space=1+532|aguru=2+1520|uni25CC=2+1044|aimatraguru=2+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A13,U+0020,U+0A73,U+0A4B:[ooguru=0+1356|space=1+532|uraguru=2+1356|uni25CC=2+1044|oomatraguru=2+0]
+../fonts/604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf::U+0A14,U+0020,U+0A05,U+0A4C:[auguru=0+1520|space=1+532|aguru=2+1520|uni25CC=2+1044|aumatraguru=2+0]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A86,U+0020,U+0A85,U+0ABE:[gid3=0+2351|gid1=1+612|gid2=2+1808|gid17=2+1044|gid10=2+543]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A8D,U+0020,U+0A85,U+0AC5:[gid4=0+1808|gid1=1+612|gid2=2+1808|gid17=2+1044|gid11=2+0]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A8F,U+0020,U+0A85,U+0AC7:[gid5=0+1808|gid1=1+612|gid2=2+1808|gid17=2+1044|gid12=2+0]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A90,U+0020,U+0A85,U+0AC8:[gid6=0+1808|gid1=1+612|gid2=2+1808|gid17=2+1044|gid13=2+0]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A91,U+0020,U+0A85,U+0AC9:[gid7=0+2351|gid1=1+612|gid2=2+1808|gid17=2+1044|gid14=2+543]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A93,U+0020,U+0A85,U+0ACB,U+0020,U+0A85,U+0ABE,U+0AC5:[gid8=0+2351|gid1=1+612|gid2=2+1808|gid17=2+1044|gid15=2+543|gid1=4+612|gid2=5+1808|gid17=5+1044|gid11=5+0|gid10=5+543]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0A94,U+0020,U+0A85,U+0ACC,U+0020,U+0A85,U+0ABE,U+0AC8:[gid9=0+2351|gid1=1+612|gid2=2+1808|gid17=2+1044|gid16=2+543|gid1=4+612|gid2=5+1808|gid17=5+1044|gid13=5+0|gid10=5+543]
+../fonts/738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf::U+0AC9,U+0020,U+0AC5,U+0ABE:[gid17=0+1044|gid14=0+543|gid1=1+612|gid17=1+1044|gid11=1+0|gid17=1+1044|gid10=1+543]
+../fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf::U+0B06,U+0020,U+0B05,U+0B3E:[aaorya=0+1681|space=1+881|aorya=2+1284|uni25CC=2+1044|aavowelsignorya=2+387]
+../fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf::U+0B10,U+0020,U+0B0F,U+0B57:[aiorya=0+1681|space=1+881|eorya=2+1315|uni25CC=2+1044|aulengthmarkorya=2+387]
+../fonts/2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf::U+0B14,U+0020,U+0B13,U+0B57:[auorya=0+1679|space=1+881|oorya=2+1309|uni25CC=2+1044|aulengthmarkorya=2+387]
+../fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf::U+0C13,U+0020,U+0C12,U+0C55:[gid3=0+1497|gid1=1+580|gid2=2+1497|gid13=2+1184|gid12=2+0]
+../fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf::U+0C14,U+0020,U+0C12,U+0C4C:[gid4=0+1497|gid1=1+580|gid2=2+1497|gid13=2+1184|gid11=2+634]
+../fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf::U+0C40,U+0020,U+0C3F,U+0C55:[gid13=0+1184|gid6=0+0|gid1=1+580|gid13=1+1184|gid5=1+0|gid13=1+1184|gid12=1+0]
+../fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf::U+0C47,U+0020,U+0C46,U+0C55:[gid13=0+1184|gid8=0+0|gid1=1+580|gid13=1+1184|gid7=1+0|gid13=1+1184|gid12=1+0]
+../fonts/03e3f463c3a985bc42096620cc415342818454fb.ttf::U+0C4B,U+0020,U+0C4A,U+0C55:[gid13=0+1184|gid10=0+634|gid1=1+580|gid13=1+1184|gid9=1+634|gid13=1+1184|gid12=1+0]
+../fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf::U+0C8A,U+0020,U+0C89,U+0CBE:[gid3=0+3269|gid1=1+590|gid2=2+2502|gid10=2+1184|gid7=2+919]
+../fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf::U+0C94,U+0020,U+0C92,U+0CCC:[gid6=0+1596|gid1=1+590|gid5=2+1590|gid10=2+1184|gid8=2+880]
+../fonts/7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf::U+0CE0,U+0020,U+0C8B,U+0CBE:[gid9=0+3214|gid1=1+590|gid4=2+2440|gid10=2+1184|gid7=2+919]
+../fonts/af85624080af5627fb050f570d148a62f04fda74.ttf::U+0D08,U+0020,U+0D07,U+0D57:[gid3=0+3574|gid1=1+632|gid2=2+2019|gid14=2+1184|gid13=2+1555]
+../fonts/af85624080af5627fb050f570d148a62f04fda74.ttf::U+0D0A,U+0020,U+0D09,U+0D57:[gid5=0+2972|gid1=1+632|gid4=2+1417|gid14=2+1184|gid13=2+1555]
+../fonts/af85624080af5627fb050f570d148a62f04fda74.ttf::U+0D10,U+0020,U+0D0E,U+0D46:[gid7=0+4073|gid1=1+632|gid6=2+2608|gid12=2+1465|gid14=2+1184]
+../fonts/af85624080af5627fb050f570d148a62f04fda74.ttf::U+0D13,U+0020,U+0D12,U+0D3E:[gid9=0+2557|gid1=1+632|gid8=2+1524|gid14=2+1184|gid11=2+1033]
+../fonts/af85624080af5627fb050f570d148a62f04fda74.ttf::U+0D14,U+0020,U+0D12,U+0D57:[gid10=0+3073|gid1=1+632|gid8=2+1524|gid14=2+1184|gid13=2+1555]
diff --git a/test/shaping/data/in-house/tests/kern-format2.tests b/test/shaping/data/in-house/tests/kern-format2.tests
new file mode 100644 (file)
index 0000000..f7cd840
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf::U+0061,U+0062,U+0063,U+0064,U+0065,U+0066,U+0067,U+0068,U+0069,U+006A,U+006B,U+006C,U+006D,U+006E,U+006F,U+0070:[a=0+626|b=1+672|c=2+564|d=3@-15,0+657|e=4+621|f=5+403|g=6@-10,0+662|h=7+666|i=8+316|j=9+316|k=10+591|l=11+316|m=12+1021|n=13+666|o=14+644|p=15+672]
+../fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf::U+0063,U+006B,U+0063,U+006B,U+0063,U+006B:[c=0+579|k=1+591|c=2+579|k=3+591|c=4+579|k=5+591]
+../fonts/e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf::U+0041,U+0056:[A=0+701|V=1@-40,0+703]
diff --git a/test/shaping/data/in-house/tests/khmer-mark-order.tests b/test/shaping/data/in-house/tests/khmer-mark-order.tests
new file mode 100644 (file)
index 0000000..d581dd1
--- /dev/null
@@ -0,0 +1,25 @@
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17BE,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni1794=3+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17BE,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17C1,U+17B8,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17B8,U+17C1,U+17BB,U+1794:[uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni17C1=0+288|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17BE,U+17BB,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17C1,U+17B8,U+17BB,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=6+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17B8,U+17C1,U+17BB,U+17BB,U+1794:[uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni17C1=0+288|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=6+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17BE,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17C1,U+17B8,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17B8,U+17C1,U+17BB,U+1794:[uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni17C1=0+288|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17BE,U+17BB,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17C1,U+17B8,U+17BB,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=6+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17B8,U+17C1,U+17BB,U+17BB,U+1794:[uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni17C1=0+288|uni25CC=0+635|uni17BB=0@-20,-26+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=6+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17BE,U+17B8,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17B8=0@-20,-84+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17B8,U+17BE,U+1794:[uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17BE,U+17B8,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17C9,U+17B8,U+17BE,U+17BB,U+1794:[uni179F=0+928|uni17C9=0@-32,-29+0|uni17B8=0@-32,237+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17BE,U+17B8,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17B8=0@-20,-84+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17B8,U+17BE,U+1794:[uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17BE,U+17B8,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17CA,U+17B8,U+17BE,U+17BB,U+1794:[uni179F=0+928|uni17BB=0@-6,-26+0|uni17B8=0@-32,-29+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=5+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17BE,U+17B8,U+17BB,U+1794:[uni17C1=0+288|uni179F=0+928|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17BE,U+17BB,U+17B8,U+1794:[uni17C1=0+288|uni179F=0+928|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni17B8=0@-20,-84+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17B8,U+17BE,U+17BB,U+1794:[uni179F=0+928|uni17B8=0@-32,-29+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni1794=4+635]
+../fonts/b6031119874ae9ff1dd65383a335e361c0962220.ttf::U+179F,U+17B8,U+17BB,U+17BE,U+1794:[uni179F=0+928|uni17B8=0@-32,-29+0|uni25CC=0+635|uni17BB=0@-20,-26+0|uni17C1=0+288|uni25CC=0+635|uni17B8=0@-20,-84+0|uni1794=4+635]
diff --git a/test/shaping/data/in-house/tests/khmer-misc.tests b/test/shaping/data/in-house/tests/khmer-misc.tests
new file mode 100644 (file)
index 0000000..a7a1c6d
--- /dev/null
@@ -0,0 +1,89 @@
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1781,U+17D2,U+1798,U+17C2:[uni17C2=0+288|uni1781=0+635|uni17D21798=0@22,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1787,U+17B6:[uni178717B6=0+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1790,U+17D2,U+1784,U+17C3:[uni17C3=0+288|uni1790=0+635|uni17D21784=0@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17B6:[uni179817B6=0+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+1796,U+17BB:[uni1798=0+635|uni17D21796=0@-1,-26+0|uni17BB=0@-22,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A:[uni179A=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17B8:[uni179A=0+288|uni17B8.r=0@76,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17CD:[uni179A=0+288|uni17CD.r=0@18,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17C5:[uni17C1=0+288|uni179F17C5=0+1216]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+17A5:[uni179A=0+288|uni17D2=0+0|uni17A5=2+635]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17B9,U+17D2,U+1788:[uni1784=0+635|uni17B9=0@-46,30+0|uni17D21788=0+234]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1788,U+17B9:[uni1784=0+635|uni17D21788=0+234|uni17B9=0@8,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+1782,U+17D2,U+179A:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1784,U+17D2,U+179A,U+17D2,U+1782:[uni17D2179A.low=0+287|uni1784=0+635|uni17D21782=0@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+200C,U+17C9,U+17D2,U+179B,U+17C1,U+17C7:[uni17C1=0+288|uni1798=0+635|space=0+0|uni17C9=0@-46,-29+0|uni17D2179B=0@-1,-26+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1794,U+17CA,U+17D0:[uni1794=0+635|uni17CA=0@-46,-29+0|uni17D0=0@-46,113+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1793,U+17C2,U+17CE:[uni17C2=0+288|uni1793=0+635|uni17CE=0@-36,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C1,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C0,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni1780=0+636|uni17C0.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C4,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017B6=0+924]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17C5,U+17D2,U+179A:[uni17D2179A=0+287|uni17C1=0+288|uni178017C5=0+924]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1796,U+17D1,U+17B6:[uni179617B6=0+923|uni17D1=0@-311,-19+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+178F,U+17D2,U+179A,U+17B6,U+1780,U+17CB:[uni1780=0+636|uni17D2179A.low=1+287|uni179317B6=1+924|uni17D2178F=1@-290,-26+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B7,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B7=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+1793,U+17D2,U+179A,U+17D2,U+179F,U+17B8,U+1780,U+17CB:[uni1780=0+636|uni17D2179A=1+287|uni1793=1+635|uni17D2179F=1+302|uni17B8=1@-4,30+0|uni1780=7+636|uni17CB=7@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B6,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F17B6=0+584|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B7,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B7=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B8,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B8=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17B9,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17B9=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BA,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BA=0@-4,30+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BB,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BB=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BC,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BC=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BD,U+1793,U+17D2,U+178F:[uni1780=0+636|uni17D2179F=0+302|uni17BD=0@1,-260+0|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1780,U+17D2,U+179F,U+17BF,U+1793,U+17D2,U+178F:[uni17C1=0+288|uni1780=0+636|uni17D2179F=0+302|uni17BF.right2=0+288|uni1793=4+635|uni17D2178F=4@-1,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B6,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C6=0@39,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17B7,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17B7=0@-4,30+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C6=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17BB,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C1,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C4,U+17C7:[uni17C1=0+288|uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F17B6.low=0+584|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C6:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C6=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1783,U+17D2,U+179B,U+17D2,U+179F,U+17C7:[uni1783=0+928|uni17D2179B=0@15,-26+0|uni17D2179F.low=0+302|uni17C7=0+386]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17BC:[uni1789=0+952|uni17BC=0@-173,-260+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BB:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BB=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BC:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BC=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1789,U+17D2,U+1789,U+17BD:[uni1789.a=0+952|uni17D21789.a=0@19,-22+0|uni17BD=0@-160,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302|uni17C0.right2=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F=0+302]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C4:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17B6=0+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+178F,U+17D2,U+179A,U+17D2,U+179F,U+17C5:[uni17C1=0+288|uni17D2179A=0+287|uni178F=0+635|uni17D2179F17C5=0+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17BB,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17BB=0@-19,-296+0|uni17C6=0@-46,-29+0|uni1780=5+636|uni17CB=5@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C4,U+1780,U+17CB:[uni17C1=0+288|uni179217B6=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C5,U+1780,U+17CB:[uni17C1=0+288|uni179217C5=0+923|uni17D2179B=0@-290,-26+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1792,U+17D2,U+179B,U+17C6,U+1780,U+17CB:[uni1792=0+635|uni17D2179B=0@-2,-26+0|uni17C6=0@-46,-29+0|uni1780=4+636|uni17CB=4@-23,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17B6:[uni179817B6=0+923|uni17D2178F=0@-289,-26+0|uni17D2179B=0@-289,-296+0|uni17C9=0@-334,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BB:[uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BB=0@-18,-566+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17BF:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1798,U+17D2,U+178F,U+17D2,U+179B,U+17C9,U+17C0:[uni17C1=0+288|uni1798=0+635|uni17D2178F=0@-1,-26+0|uni17D2179B=0@-1,-296+0|uni17C9=0@-46,-29+0|uni17C0.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+1799,U+17D2,U+1799,U+17BE,U+17A0,U+17D2,U+179C,U+17D2,U+179B,U+17C3:[uni17C1=0+288|uni1799=0+953|uni17D21799=0+298|uni17B8=0@1,30+0|uni17C3=4+288|uni17A0=4+928|uni17D2179C=4@20,-26+0|uni17D2179B=4@19,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179A,U+17D2,U+179A:[uni17D2179A=0+287|uni179A=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B6:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni178417B6=10+923]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B7:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B7=10@-46,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17B6,U+179F,U+17D2,U+178F,U+17D2,U+179A,U+1783,U+17D2,U+1788,U+1784,U+17B8:[uni179F17B6=0+1216|uni17D2179A=2+287|uni179F=2+928|uni17D2178F=2@14,-26+0|uni1783=7+928|uni17D21788=7+234|uni1784=10+635|uni17B8=10@-46,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+178F,U+17D2,U+179A,U+17B8,U+179C,U+17D0,U+1781,U+17D2,U+1789,U+17D2,U+179F,U+17B6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0|uni179C=6+326|uni17D0=6@139,40+0|uni1781=8+635|uni17D21789=8@-4,-26+0|uni17D2179F17B6.low=8+584]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B6:[uni17D2179A=0+287|uni179F17B6=0+1216|uni17D2178F=0@-274,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B7:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B7=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B8:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17B9:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B9=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BA:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BB:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BB=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BC:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BC=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BD:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BD=0@-6,-296+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BE:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17B8=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17BF.right2=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17BF:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C0:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C0.right1.high=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C1:[uni17C1=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C2:[uni17C2=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C3:[uni17C3=0+288|uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+179F,U+17D2,U+179A,U+17D2,U+178F,U+17CA,U+17C6:[uni17D2179A=0+287|uni179F=0+928|uni17D2178F=0@14,-26+0|uni17CA=0@-32,-29+0|uni17C6=0@-32,113+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BE:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17BB=0+0|uni17B8=0@-4,30+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17BF:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17BF.right1=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+1782,U+17D2,U+179F,U+17CA,U+17C0:[uni17C1=0+288|uni17A0=0+928|uni17D21782=0@20,-26+0|uni17D2179F.low=0+302|uni17CA=0@-4,30+0|uni17C0.right1.high=0+288]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+1784,U+17D2,U+1780:[uni17D2179A=0+287|uni17A0=0+928|uni17D2179C=0@20,-26+0|uni1784=5+635|uni17D21780=5@0,-26+0]
+../fonts/3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf::U+17A0,U+17D2,U+179A,U+17D2,U+179C,U+17B6,U+17C6,U+1784:[uni17D2179A=0+287|uni17A017B6=0+1216|uni17D2179C=0@-268,-26+0|uni17C6=0@47,-29+0|uni1784=7+635]
index 4c62113..c7be180 100644 (file)
@@ -10,3 +10,4 @@
 ../fonts/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-HK:U+004A:[gid6=0+1000]
 ../fonts/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-mo:U+004A:[gid6=0+1000]
 ../fonts/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-Hant-mo:U+004A:[gid6=0+1000]
+../fonts/d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf:--language=dv --no-glyph-names:U+007C:[2=0+156]
diff --git a/test/shaping/data/in-house/tests/macos.tests b/test/shaping/data/in-house/tests/macos.tests
new file mode 100644 (file)
index 0000000..7855c0d
--- /dev/null
@@ -0,0 +1,37 @@
+# 10.12.6 https://gist.github.com/ebraminio/1704341fa16b06979e605aafd88198cf
+/System/Library/Fonts/Helvetica.dfont@c7bec2785a4c402b7809b5e35337c3d24c18e281:--font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
+/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
+/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--font-funcs ot:U+0066,U+0069:[fi=0+1139]
+/Library/Fonts/Khmer MN.ttc@5f5b1072df99b7355d3066ea85fe82969d13c94a:--font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
+/Library/Fonts/Tamil MN.ttc@37a2020c3f86ebcc45e02c1de5fdf81e2676989d:--font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
+/System/Library/Fonts/Times.dfont@39c954614d3f3317b28564db06d5b7b7a6ff0e39:--font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-551,588+0|fi=3+1139|Z=5+1251]
+/System/Library/Fonts/LucidaGrande.ttc@d89a9d7e57767bfe3b5a4cfd22bb1e9dbe03a062:--font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@51,0+0|samekhhebrew=0+1361]
+/Library/Fonts/Apple Chancery.ttf@5fc49ae9bce39e2105864323183b68ea34c9e562:--font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
+/Library/Fonts/Apple Chancery.ttf@5fc49ae9bce39e2105864323183b68ea34c9e562:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[T=0+1497|e=1@-62,0+699|space=2+569|A=3+1431|V=4@-37,0+1377|space=5+569|T=6+1510|r=7@-50,0+803|space=8+569|V=9+1376|a=10@-37,0+1014|space=11+569|r=12+853|T=13+1560|space=14+569|e=15+761|T=16+1560|space=17+569|T=18+1515|d=19@-45,0+1006]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
+/System/Library/Fonts/GeezaPro.ttc@f43ee7151c2e9f1dddfbc26cfc148609eb5c5820:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
+/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0+1105|gid584=1@-105,0+979|gid3=2+490|gid4=3+1227|gid265=4@-65,0+1227|gid3=5+490|gid225=6+1130|gid728=7@-80,0+569|gid3=8+490|gid265=9+1227|gid505=10@-65,0+997|gid3=11+490|gid728=12+609|gid225=13@-40,0+1170|gid3=14+490|gid584=15+1004|gid225=16@-80,0+1130|gid3=17+490|gid225=18+1105|gid576=19@-105,0+1068]
+/System/Library/Fonts/SFNSDisplay.ttf@92787c30716672737e9059bc367c15d04fbc1ced:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid225=0@46,0+1197|gid584=1@-59,0+1071|gid3=2@46,0+582|gid4=3@46,0+1319|gid265=4@-19,0+1319|gid3=5@46,0+582|gid225=6@46,0+1222|gid728=7@-34,0+661|gid3=8@46,0+582|gid265=9@46,0+1319|gid505=10@-19,0+1089|gid3=11@46,0+582|gid728=12@46,0+701|gid225=13@6,0+1262|gid3=14@46,0+582|gid584=15@46,0+1096|gid225=16@-34,0+1222|gid3=17@46,0+582|gid225=18@46,0+1197|gid576=19@-59,0+1160]
+/System/Library/Fonts/Apple Color Emoji.ttc@d2fe8a134483aa48a43a9d1e4b7204d37a4abdf5:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
+/Library/Fonts/Zapfino.ttf@9ee799ffb09516ead6b0cf6f2ca807276e150748:--font-funcs ot:U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+006F:[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|Z=6+416|a=7@-21,0+264|p_f=8+433|i=10+181|n=11+261|Z=12+416|a=13@-21,0+264|p_f=14+433|i=16+181|n=17+261|Z=18+416|a=19@-21,0+264|p_f=20+433|i=22+181|n=23+261|Z=24+416|a=25@-21,0+264|p_f=26+433|i=28+181|n=29+261|Z=30+416|a=31@-21,0+264|p_f=32+433|i=34+181|n=35+261|Z=36+416|a=37@-21,0+264|p_f=38+433|i=40+181|n=41+261|Z=42+416|a=43@-21,0+264|p_f=44+433|i=46+181|n=47+261|Z=48+416|a=49@-21,0+264|p_f=50+433|i=52+181|n=53+261|Z=54+416|a=55@-21,0+264|p_f=56+433|i=58+181|n=59+261|Z=60+416|a=61@-21,0+264|p_f=62+433|i=64+181|n=65+261|Z_a_p_f_i_n_o=66+2333]
+
+# 10.13.6 https://gist.github.com/ebraminio/d432e831b3f7ebe30245dde5775e1c7e
+/System/Library/Fonts/Helvetica.ttc@8a928f9866299d2455f41360202b7a3b48503a5e:--font-funcs ot:U+006D,U+0300:[m=0+1706|gravecmb=0@-284,10+0]
+/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--font-funcs ot:U+006D,U+0300:[mgrave=0+1912]
+/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--font-funcs ot:U+0066,U+0069:[fi=0+1139]
+/Library/Fonts/Khmer MN.ttc@782ba6cf3fca0512ab348dfe08345a2d5dc5bf2c:--font-funcs ot:U+17A2,U+1780,U+17D2,U+179F,U+179A,U+1781,U+17D2,U+1798,U+17C2,U+179A:[km_qa=0+1025|km_ka=1+1025|km_sa.sub=1+517|km_ro=4+593|km_vs_ae=5+605|km_kha=5+1025|km_mo.sub=5+0|km_ro=9+593]
+/Library/Fonts/Tamil MN.ttc@3de37f3f8f3cb6015b093fbd6e9d323daaf6fb1d:--font-funcs ot:U+0BA4,U+0BCA,U+0B95,U+0BC1,U+0B95,U+0BCD,U+0B95,U+0BAA,U+0BCD,U+0BAA,U+0B9F,U+0BCD,U+0B9F,U+0BC1:[tgm_e=0+1702|tgc_ta=0+1598|tgm_aa=0+1149|tgc_ku=2+1962|tgc_k=4+1592|tgc_ka=6+1592|tgc_p=7+1370|tgc_pa=9+1370|tgc_tt=10+1596|tgc_ttu=12+1833]
+/System/Library/Fonts/Times.ttc@896098b6979306ad84355025459f7c68b029139c:--font-funcs ot:U+0041,U+0066,U+0300,U+0066,U+0069,U+005A:[A=0+1479|f=1+682|gravecmb=1@-551,588+0|fi=3+1139|Z=5+1251]
+/System/Library/Fonts/LucidaGrande.ttc@63ba1b1de4709bd832ca76bd62368dd99fc34269:--font-funcs ot:U+05E1,U+05B0:[shevahebrew=0@51,0+0|samekhhebrew=0+1361]
+/Library/Fonts/Apple Chancery.ttf@4ec49cba0d4e68d025ada0498c4df1b2f9fd57ac:--font-funcs ot:U+0054,U+0068,U+0020,U+0074,U+0068,U+0020,U+006C,U+006C,U+0020,U+0074,U+0065,U+0020,U+0074,U+006F,U+0020,U+0074,U+0072,U+0020,U+0066,U+0072,U+0020,U+0066,U+0075,U+0020,U+0066,U+006A:[T_h=0+2308|space=2+569|t_h=3+1687|space=5+569|l_l=6+1108|space=8+569|t_e=9+1408|space=11+569|t_o=12+1531|space=14+569|t_r=15+1385|space=17+569|f_r=18+1432|space=20+569|f_u=21+1733|space=23+569|f_j=24+1098]
+/Library/Fonts/Apple Chancery.ttf@4ec49cba0d4e68d025ada0498c4df1b2f9fd57ac:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[T=0+1497|e=1@-62,0+699|space=2+569|A=3+1431|V=4@-37,0+1377|space=5+569|T=6+1510|r=7@-50,0+803|space=8+569|V=9+1376|a=10@-37,0+1014|space=11+569|r=12+853|T=13+1560|space=14+569|e=15+761|T=16+1560|space=17+569|T=18+1515|d=19@-45,0+1006]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0627,U+0644,U+0623,U+064E,U+0628,U+0652,U+062C,U+064E,U+062F,U+0650,U+064A,U+064E,U+0651,U+0629,U+0640,U+0627,U+0644,U+0639,U+064E,U+0631,U+064E,U+0628,U+0650,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064A,U+064E,U+0651,U+0629:[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0631,U+0628:[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
+/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334:--font-funcs ot:U+0628,U+064F:[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
+/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0+1055|gid658=1@-135,0+914|gid3=2+420|gid4=3+1227|gid332=4@-65,0+1227|gid3=5+420|gid282=6+1075|gid813=7@-115,0+516|gid3=8+420|gid332=9+1217|gid572=10@-75,0+953|gid3=11+420|gid813=12+546|gid282=13@-85,0+1105|gid3=14+420|gid658=15+914|gid282=16@-135,0+1055|gid3=17+420|gid282=18+1055|gid649=19@-135,0+999]
+/System/Library/Fonts/SFNSDisplay.ttf@c8948f464ff822a5f9bbf2e12d0e4e32268815aa:--font-ptem 9 --font-funcs ot:U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064:[gid282=0@46,0+1147|gid658=1@-89,0+1006|gid3=2@46,0+512|gid4=3@46,0+1319|gid332=4@-19,0+1319|gid3=5@46,0+512|gid282=6@46,0+1167|gid813=7@-69,0+608|gid3=8@46,0+512|gid332=9@46,0+1309|gid572=10@-29,0+1045|gid3=11@46,0+512|gid813=12@46,0+638|gid282=13@-39,0+1197|gid3=14@46,0+512|gid658=15@46,0+1006|gid282=16@-89,0+1147|gid3=17@46,0+512|gid282=18@46,0+1147|gid649=19@-89,0+1091]
+/System/Library/Fonts/Apple Color Emoji.ttc@2e09b1f3d42c3821cc6c4ac5b6ce16237ab0d496:--remove-default-ignorables --font-funcs ot:U+1F468,U+200D,U+1F469,U+200D,U+1F467,U+200D,U+1F466:[u1F46A.MWGB=0+800]
+/Library/Fonts/Zapfino.ttf@99a1e15163c3e9567d5b1019c45e9254dae63b08:--font-funcs ot:U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+005A,U+0061,U+0070,U+0066,U+0069,U+006E,U+006F:[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|Z=6+416|a=7@-21,0+264|p_f=8+433|i=10+181|n=11+261|Z=12+416|a=13@-21,0+264|p_f=14+433|i=16+181|n=17+261|Z=18+416|a=19@-21,0+264|p_f=20+433|i=22+181|n=23+261|Z=24+416|a=25@-21,0+264|p_f=26+433|i=28+181|n=29+261|Z=30+416|a=31@-21,0+264|p_f=32+433|i=34+181|n=35+261|Z=36+416|a=37@-21,0+264|p_f=38+433|i=40+181|n=41+261|Z=42+416|a=43@-21,0+264|p_f=44+433|i=46+181|n=47+261|Z=48+416|a=49@-21,0+264|p_f=50+433|i=52+181|n=53+261|Z=54+416|a=55@-21,0+264|p_f=56+433|i=58+181|n=59+261|Z=60+416|a=61@-21,0+264|p_f=62+433|i=64+181|n=65+261|Z_a_p_f_i_n_o=66+2333]
index efb4cf4..c5e35c8 100644 (file)
@@ -1,4 +1,19 @@
 ../fonts/37033cc5cf37bb223d7355153016b6ccece93b28.ttf::U+1826,U+180B,U+1826:[uni1826.E85E_ue.init1=0+599|uni1826.E856_ue.fina=2+750]
 ../fonts/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf::U+1820,U+180B:[uni1820.E821_a.isol1=0+1199]
-../fonts/bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf::U+183A,U+1823,U+182E,U+182B,U+1822,U+1826,U+180B,U+1832,U+180B,U+1827,U+1837,U+0020,U+182D,U+182D,U+180B,U+0020,U+182D,U+180C,U+0020,U+182D,U+180D,U+200D,U+0020,U+182D,U+200D,U+182D,U+180B,U+200D,U+0020,U+182D,U+180C,U+200D,U+0020,U+182D,U+180D,U+200D,U+0020,U+200D,U+182D,U+200D,U+200D,U+182D,U+180B,U+200D,U+0020,U+200D,U+182D,U+180C,U+200D,U+0020,U+200D,U+182D,U+180D,U+200D,U+0020,U+200D,U+182D,U+200D,U+182D,U+180B,U+0020,U+200D,U+182D,U+180C,U+0020,U+1820,U+200C,U+182D,U+1820,U+1837,U+0020,U+1830,U+1824,U+1837,U+200D,U+200D,U+182D,U+1820,U+200D,U+0020,U+200D,U+182D,U+1824,U+182F,U+1822,U+0020,U+182A,U+1820,U+1822,U+182D,U+180E,U+1820,U+202F,U+1836,U+1822,U+1828:[uni183A1823.E971_ko.init=0+950|uni182E.E904_m.medi=2+400|uni182B1822.E8A6_pi.medi=3+1150|uni1826.E854_ue.medi1=5+1100|uni1832.E916_t.medi1=7+1000|uni1827.E85C_ee.medi=9+750|uni1837.E931_r.fina=10+750|space=11+500|uni182D.E8E2_g.init=12+1000|uni182D.E8E8_g.fina1=13+1250|space=15+500|uni182D.EA1B_g.isol2=16+1000|space=18+500|uni182D.EA1E_g.init3=19+650|space=19+0|space=22+500|uni182D.E8E2_g.init=23+1000|space=23+0|uni182D.E8E5_g.medi1=25+800|space=25+0|space=28+500|uni182D.EA1D_g.init2=29+950|space=29+0|space=32+500|uni182D.EA1E_g.init3=33+650|space=33+0|space=36+500|space=36+0|uni182D.E8E4_g.medi=38+800|space=38+0|space=38+0|uni182D.E8E5_g.medi1=41+800|space=41+0|space=44+500|space=44+0|uni182D.E8E6_g.medi2=46+650|space=46+0|space=49+500|space=49+0|uni182D.E8E6_g.medi2=51+650|space=51+0|space=54+500|space=54+0|uni182D.E8E4_g.medi=56+800|space=56+0|uni182D.E8E8_g.fina1=58+1250|space=60+500|space=60+0|uni182D.E8E9_g.fina2=62+1050|space=64+500|uni1820.E820_a.isol=65+1550|space=65+0|uni182D.E8E2_g.init=67+1000|uni1820.E823_a.medi=68+400|uni1837.E931_r.fina=69+750|space=70+500|uni1830.E90B_s.init=71+850|uni1824.E844_u.medi=72+600|uni1837.E930_r.medi=73+600|space=73+0|space=73+0|uni182D.E8E5_g.medi1=76+800|uni1820.E823_a.medi=77+400|space=77+0|space=79+500|space=79+0|uni182D.E8E5_g.medi1=81+800|uni1824.E844_u.medi=82+600|uni182F.E908_l.medi=83+400|uni1822.E837_i.fina=84+600|space=85+500|uni182A1820.E875_ba.init=86+1000|uni1822.E836_i.medi2=88+1000|uni182D.E8E8_g.fina1=89+1250|space=90+0|uni1820.E827_a.fina2=91+600|uni202F.nobreak=92+500|uni1836.E92B_y.init1=93+500|uni1822.E834_i.medi=94+500|uni1828.E866_n.fina=95+850]
 ../fonts/a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttf::U+180A,U+1868,U+180A,U+1868,U+180B,U+180A,U+1868,U+180C,U+180A,U+1868,U+180D,U+180A:[gid1=0+268|gid10=1+778|gid1=2+268|gid9=3+575|gid1=5+268|gid10=6+778|gid1=8+268|gid8=9+575|gid1=11+268]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+183A,U+1823,U+182E,U+182B,U+1822,U+1826,U+180B,U+1832,U+180B,U+1827,U+1837:[uni183A1823.E971_ko.init=0+950|uni182E.E904_m.medi=2+400|uni182B1822.E8A6_pi.medi=3+1150|uni1826.E854_ue.medi1=5+1100|uni1832.E916_t.medi1=7+1000|uni1827.E85C_ee.medi=9+750|uni1837.E931_r.fina=10+750]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+182D,U+180B:[uni182D.E8E2_g.init=0+1000|uni182D.E8E8_g.fina1=1+1250]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+180C:[uni182D.EA1B_g.isol2=0+1000]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+180D,U+200D:[uni182D.EA1E_g.init3=0+650|space=0+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+200D,U+182D,U+180B,U+200D:[uni182D.E8E2_g.init=0+1000|space=0+0|uni182D.E8E5_g.medi1=2+800|space=2+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+180C,U+200D:[uni182D.EA1D_g.init2=0+950|space=0+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182D,U+180D,U+200D:[uni182D.EA1E_g.init3=0+650|space=0+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+200D,U+200D,U+182D,U+180B,U+200D:[space=0+0|uni182D.E8E4_g.medi=1+800|space=1+0|space=1+0|uni182D.E8E5_g.medi1=4+800|space=4+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+180C,U+200D:[space=0+0|uni182D.E8E6_g.medi2=1+650|space=1+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+180D,U+200D:[space=0+0|uni182D.E8E6_g.medi2=1+650|space=1+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+200D,U+182D,U+180B:[space=0+0|uni182D.E8E4_g.medi=1+800|space=1+0|uni182D.E8E8_g.fina1=3+1250]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+180C:[space=0+0|uni182D.E8E9_g.fina2=1+1050]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+1820,U+200C,U+182D,U+1820,U+1837:[uni1820.E820_a.isol=0+1550|space=1+0|uni182D.E8E2_g.init=2+1000|uni1820.E823_a.medi=3+400|uni1837.E931_r.fina=4+750]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+1830,U+1824,U+1837,U+200D,U+200D,U+182D,U+1820,U+200D:[uni1830.E90B_s.init=0+850|uni1824.E844_u.medi=1+600|uni1837.E930_r.medi=2+600|space=2+0|space=2+0|uni182D.E8E5_g.medi1=5+800|uni1820.E823_a.medi=6+400|space=6+0]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+200D,U+182D,U+1824,U+182F,U+1822:[space=0+0|uni182D.E8E5_g.medi1=1+800|uni1824.E844_u.medi=2+600|uni182F.E908_l.medi=3+400|uni1822.E837_i.fina=4+600]
+../fonts/4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf::U+182A,U+1820,U+1822,U+182D,U+180E,U+1820,U+202F,U+1836,U+1822,U+1828:[uni182A1820.E875_ba.init=0+1000|uni1822.E836_i.medi2=2+1000|uni182D.E8E8_g.fina1=3+1250|space=4+0|uni1820.E827_a.fina2=5+600|uni202F.nobreak=6+500|uni1836.E92B_y.init1=7+500|uni1822.E834_i.medi=8+500|uni1828.E866_n.fina=9+850]
diff --git a/test/shaping/data/in-house/tests/myanmar-zawgyi.tests b/test/shaping/data/in-house/tests/myanmar-zawgyi.tests
new file mode 100644 (file)
index 0000000..b79d4fb
--- /dev/null
@@ -0,0 +1 @@
+../fonts/ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf:--script=Qaag:U+1000,U+103A,U+1004,U+1037,U+1039,U+1041:[Ka=0+2217|Ya-Semivowel=0+286|Nga=2+1247|Dot Below=2+0|Virama-Killer=2+0|One-Myanmar=5+1247]
diff --git a/test/shaping/data/in-house/tests/rand.tests b/test/shaping/data/in-house/tests/rand.tests
new file mode 100644 (file)
index 0000000..df324b9
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=-rand:U+0054,U+0055,U+0056:[1=0+560|2=1+602|3=2+602]
+../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602]
+../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[5=0+560|7=1+602|10=2+602|4=3+560|7=4+602|10=5+602|6=6+560|9=7+602|10=8+602|5=9+560|8=10+602|12=11+602]
index 3ebaac5..ea90998 100644 (file)
 ../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+202F:[gid1=0+280]
 ../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+205F:[gid1=0+455]
 ../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot:U+3000:[gid1=0+2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+0020:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+00A0:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+1680:[gid0=0@-346,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2000:[gid1=0@-280,0+0,-1024]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2001:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2002:[gid1=0@-280,0+0,-1024]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2003:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2004:[gid1=0@-280,0+0,-683]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2005:[gid1=0@-280,0+0,-512]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2006:[gid1=0@-280,0+0,-341]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2007:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2008:[gid1=0@-280,0+0,-2048]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+2009:[gid1=0@-280,0+0,-410]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+200A:[gid1=0@-280,0+0,-128]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+202F:[gid1=0@-280,0+0,-1024]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+205F:[gid1=0@-280,0+0,-455]
+../fonts/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf:--font-funcs=ot --direction=ttb:U+3000:[gid1=0@-280,0+0,-2048]
diff --git a/test/shaping/data/in-house/tests/use-indic3.tests b/test/shaping/data/in-house/tests/use-indic3.tests
new file mode 100644 (file)
index 0000000..8c3ae13
--- /dev/null
@@ -0,0 +1 @@
+../fonts/3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf::U+0C95,U+0CCD,U+0CB0:[uni0C95=0+1176|uni0CB0_uni0CCD.blwf=0+275]
index 5d2fab3..6a247ed 100644 (file)
@@ -6,3 +6,7 @@
 ../fonts/373e67bf41ca264e260a9716162b71a23549e885.ttf:--no-glyph-names:U+A8AC,U+A8B4,U+A8B5:[2=0+377|3=0+242|4=0+210]
 ../fonts/59a585a63b3df608fbeef00956c8c108deec7de6.ttf:--no-glyph-names:U+1BC7,U+1BEA,U+1BF3:[1=0+749|2=0+402|4=0+535|3=0+401]
 ../fonts/1ed7e9064f008f62de6ff0207bb4dd29409597a5.ttf::U+11064,U+1107F,U+11052,U+11065,U+1107F,U+11053:[brm_num100.1=0+2224|brm_num1000.2=3+1834]
+../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+11042,U+11046:[brm_KA=0+754|brm_vowelEE=0@-383,0+0|brm_virama=0@-524,0+0]
+../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+11044,U+11046:[brm_KA=0+754|brm_vowelOO=0@-647,0+0|brm_virama=0@-524,0+0]
+../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+1103C:[brm_KA=0+754|brm_vowelU=0@-403,0+0]
+../fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf::U+111C8,U+111C9,U+111C9:[u111C8=0+500|u111C9=0@-500,0+0|u111C9=0@-500,0+0]
index 172946c..dd2a3a2 100644 (file)
@@ -2,4 +2,13 @@
 ../fonts/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+0|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212]
 ../fonts/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+1211|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212]
 ../fonts/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf:--font-funcs=ot:U+11103,U+11128:[u11103=0+837|u11128=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+1112E:[u11124=0+514|u11131=0+0|u11127=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11131,U+11127:[u11124=0+514|u11131=0+0|u11127=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11127,U+11131:[u11124=0+514|u11127=0+0|uni25CC=0+547|u11131=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11134,U+11131:[u11124=0+514|u11134=0+0|u11131=0+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11131,U+11134:[u11124=0+514|u11131=0+0|uni25CC=0+547|u11134=0+0]
 ../fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf:--font-funcs=ft:U+11410,U+11442,U+11411,U+11440,U+11443,U+11410,U+11442,U+11411,U+11441,U+11443:[E_dv.alt=0+275|Ga.icd=0+367|Gha.diag=0@100,0+386|AA_dv.alt=0+208|Candrabindu=0@17,-8+0|E_dv.alt=5+275|Ga.icd=5+367|Gha.diag=5@100,0+386|AU_dv_part.alt=5+213|Candrabindu.sm=5@-52,179+0]
+../fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf::U+11328,U+1134D,U+1CF4:[gid1=0+793|gid2=0+0|gid3=0+0]
+../fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf::U+1C00,U+1C27,U+1C28,U+1C34,U+1C35:[uni1C35=0+500|uni1C34=0+500|uni1C28=0+500|uni1C27=0+500|uni1C00=0+500]
+../fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf::U+0D4E,U+0D15,U+0D4D,U+0D15,U+0D46:[uni0D15=0+500|uni0D4E=0+500|uni0D4D=0+500|uni0D46=3+500|uni0D15=3+500]
+../fonts/4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf::U+1102D,U+11046,U+11013,U+11046,U+11013,U+11046:[u11013=0+500|u11046_u11013=0+500|u1102D_u11046=0+500|u11046=0+500]
index 17df28e..3958813 100644 (file)
@@ -1,3 +1,4 @@
 ../fonts/191826b9643e3f124d865d617ae609db6a2ce203.ttf:--direction=t --font-funcs=ft:U+300C:[uni300C.vert=0@-512,-578+0,-1024]
 ../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ft:U+0041,U+0042:[gid1=0@-654,-2128+0,-2789|gid2=1@-665,-2125+0,-2789]
-../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-2189+0,-2789|gid2=1@-665,-2189+0,-2789]
+../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-1468+0,-2048|gid2=1@-665,-1462+0,-2048]
+../fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf:--direction=t --font-funcs=ot:U+FF38:[gid2=0@-500,-867+0,-1000]
index c164de2..ca784f5 100644 (file)
@@ -94,12 +94,26 @@ TESTS = tests/AVAR-1.tests tests/CFF-1.tests tests/CFF2-1.tests \
        tests/CVAR-1.tests tests/CVAR-2.tests tests/GLYF-1.tests \
        tests/GPOS-1.tests tests/GPOS-2.tests tests/GPOS-3.tests \
        tests/GPOS-4.tests tests/GPOS-5.tests tests/GSUB-1.tests \
-       tests/GSUB-2.tests tests/GVAR-1.tests tests/GVAR-2.tests \
-       tests/GVAR-3.tests tests/GVAR-4.tests tests/GVAR-5.tests \
-       tests/GVAR-6.tests tests/GVAR-7.tests tests/GVAR-8.tests \
-       tests/GVAR-9.tests tests/HVAR-1.tests tests/HVAR-2.tests \
-       tests/KERN-1.tests tests/KERN-2.tests tests/SHBALI-3.tests \
-       tests/SHKNDA-1.tests $(am__EXEEXT_1)
+       tests/GSUB-2.tests tests/GSUB-3.tests tests/GVAR-1.tests \
+       tests/GVAR-2.tests tests/GVAR-3.tests tests/GVAR-4.tests \
+       tests/GVAR-5.tests tests/GVAR-6.tests tests/GVAR-7.tests \
+       tests/GVAR-8.tests tests/GVAR-9.tests tests/HVAR-1.tests \
+       tests/HVAR-2.tests tests/KERN-1.tests tests/KERN-2.tests \
+       tests/MORX-10.tests tests/MORX-11.tests tests/MORX-12.tests \
+       tests/MORX-13.tests tests/MORX-14.tests tests/MORX-16.tests \
+       tests/MORX-17.tests tests/MORX-18.tests tests/MORX-19.tests \
+       tests/MORX-1.tests tests/MORX-20.tests tests/MORX-21.tests \
+       tests/MORX-22.tests tests/MORX-23.tests tests/MORX-24.tests \
+       tests/MORX-25.tests tests/MORX-26.tests tests/MORX-27.tests \
+       tests/MORX-28.tests tests/MORX-29.tests tests/MORX-2.tests \
+       tests/MORX-30.tests tests/MORX-31.tests tests/MORX-32.tests \
+       tests/MORX-33.tests tests/MORX-34.tests tests/MORX-35.tests \
+       tests/MORX-36.tests tests/MORX-37.tests tests/MORX-38.tests \
+       tests/MORX-39.tests tests/MORX-3.tests tests/MORX-40.tests \
+       tests/MORX-41.tests tests/MORX-4.tests tests/MORX-5.tests \
+       tests/MORX-6.tests tests/MORX-7.tests tests/MORX-8.tests \
+       tests/MORX-9.tests tests/SHBALI-3.tests tests/SHKNDA-1.tests \
+       $(am__EXEEXT_1)
 subdir = test/shaping/data/text-rendering-tests
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
@@ -107,8 +121,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -458,6 +471,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -540,32 +555,8 @@ TEST_EXTENSIONS = .tests
 TESTS_LOG_COMPILER = $(srcdir)/../../run-tests.py $(top_builddir)/util/hb-shape$(EXEEXT)
 DISBALED_TESTS = \
        tests/CMAP-3.tests \
-       tests/MORX-10.tests \
-       tests/MORX-11.tests \
-       tests/MORX-12.tests \
-       tests/MORX-13.tests \
-       tests/MORX-14.tests \
-       tests/MORX-16.tests \
-       tests/MORX-17.tests \
-       tests/MORX-18.tests \
-       tests/MORX-19.tests \
-       tests/MORX-1.tests \
-       tests/MORX-20.tests \
-       tests/MORX-21.tests \
-       tests/MORX-22.tests \
-       tests/MORX-23.tests \
-       tests/MORX-25.tests \
-       tests/MORX-26.tests \
-       tests/MORX-27.tests \
-       tests/MORX-28.tests \
-       tests/MORX-2.tests \
-       tests/MORX-3.tests \
-       tests/MORX-4.tests \
-       tests/MORX-5.tests \
-       tests/MORX-6.tests \
-       tests/MORX-7.tests \
-       tests/MORX-8.tests \
-       tests/MORX-9.tests \
+       tests/MORX-31.tests \
+       tests/MORX-41.tests \
        tests/SHARAN-1.tests \
        tests/SHBALI-1.tests \
        tests/SHBALI-2.tests \
index 4be9d05..ccbbb37 100644 (file)
@@ -15,6 +15,7 @@ TESTS = \
        tests/GPOS-5.tests \
        tests/GSUB-1.tests \
        tests/GSUB-2.tests \
+       tests/GSUB-3.tests \
        tests/GVAR-1.tests \
        tests/GVAR-2.tests \
        tests/GVAR-3.tests \
@@ -28,12 +29,6 @@ TESTS = \
        tests/HVAR-2.tests \
        tests/KERN-1.tests \
        tests/KERN-2.tests \
-       tests/SHBALI-3.tests \
-       tests/SHKNDA-1.tests \
-       $(NULL)
-
-DISBALED_TESTS = \
-       tests/CMAP-3.tests \
        tests/MORX-10.tests \
        tests/MORX-11.tests \
        tests/MORX-12.tests \
@@ -48,18 +43,40 @@ DISBALED_TESTS = \
        tests/MORX-21.tests \
        tests/MORX-22.tests \
        tests/MORX-23.tests \
+       tests/MORX-24.tests \
        tests/MORX-25.tests \
        tests/MORX-26.tests \
        tests/MORX-27.tests \
        tests/MORX-28.tests \
+       tests/MORX-29.tests \
        tests/MORX-2.tests \
+       tests/MORX-30.tests \
+       tests/MORX-31.tests \
+       tests/MORX-32.tests \
+       tests/MORX-33.tests \
+       tests/MORX-34.tests \
+       tests/MORX-35.tests \
+       tests/MORX-36.tests \
+       tests/MORX-37.tests \
+       tests/MORX-38.tests \
+       tests/MORX-39.tests \
        tests/MORX-3.tests \
+       tests/MORX-40.tests \
+       tests/MORX-41.tests \
        tests/MORX-4.tests \
        tests/MORX-5.tests \
        tests/MORX-6.tests \
        tests/MORX-7.tests \
        tests/MORX-8.tests \
        tests/MORX-9.tests \
+       tests/SHBALI-3.tests \
+       tests/SHKNDA-1.tests \
+       $(NULL)
+
+DISBALED_TESTS = \
+       tests/CMAP-3.tests \
+       tests/MORX-31.tests \
+       tests/MORX-41.tests \
        tests/SHARAN-1.tests \
        tests/SHBALI-1.tests \
        tests/SHBALI-2.tests \
index 36963e5..f1722b5 100755 (executable)
@@ -28,12 +28,13 @@ def glyphstr(glyphs):
 
 html = ET.fromstring(sys.stdin.read())
 found = False
+
 for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces):
        found = True
        name = elt.get(ns('ft:id'))
        text = elt.get(ns('ft:render'))
        font = elt.get(ns('ft:font'))
-       vars = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',')
+       variations = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',')
        glyphs = []
        for use in elt.findall(".//use"):
                x = int(use.get('x'))
@@ -43,8 +44,19 @@ for elt in html.findall(".//*[@class='expected'][@ft:id]", namespaces):
                glyphname = '.'.join(href[1:].split('/')[1].split('.')[1:])
                glyphs.append((glyphname, x, y))
        opts = '--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft'
-       if vars:
-               opts = opts + ' --variations=%s' % vars
+       if variations:
+               opts = opts + ' --variations=%s' % variations
        print ("../fonts/%s:%s:%s:%s" % (font, opts, unistr(text), glyphstr(glyphs)))
 
+for elt in html.findall(".//*[@class='expected-no-crash'][@ft:id]", namespaces):
+       found = True
+       name = elt.get(ns('ft:id'))
+       text = elt.get(ns('ft:render'))
+       font = elt.get(ns('ft:font'))
+       variations = elt.get(ns('ft:var'), '').replace(':', '=').replace(';', ',')
+       opts = ''
+       if variations:
+               opts = '--variations=%s' % variations
+       print ("../fonts/%s:%s:%s:*" % (font, opts, unistr(text)))
+
 sys.exit(0 if found else 1)
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf
new file mode 100644 (file)
index 0000000..8fce4ac
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestGSUBThree.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf
new file mode 100644 (file)
index 0000000..07e6882
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-0.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf
new file mode 100644 (file)
index 0000000..58dd961
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestGVAR-Composite-Missing.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf
new file mode 100644 (file)
index 0000000..37d0b63
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXForty.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXFourtyone.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXFourtyone.ttf
new file mode 100644 (file)
index 0000000..98ebe33
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXFourtyone.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyeight.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyeight.ttf
new file mode 100644 (file)
index 0000000..29a41d0
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyeight.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf
new file mode 100644 (file)
index 0000000..f157063
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfive.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf
new file mode 100644 (file)
index 0000000..a70dadc
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyfour.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtynine.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtynine.ttf
new file mode 100644 (file)
index 0000000..c106ae9
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtynine.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyone.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyone.ttf
new file mode 100644 (file)
index 0000000..c64c12c
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyone.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf
new file mode 100644 (file)
index 0000000..22057f1
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtyseven.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtysix.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtysix.ttf
new file mode 100644 (file)
index 0000000..6676e52
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtysix.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf
new file mode 100644 (file)
index 0000000..5cab73e
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtythree.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtytwo.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtytwo.ttf
new file mode 100644 (file)
index 0000000..07ed76c
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXThirtytwo.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentyfour.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentyfour.ttf
new file mode 100644 (file)
index 0000000..271dddb
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentyfour.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentynine.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentynine.ttf
new file mode 100644 (file)
index 0000000..9f015ca
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentynine.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf b/test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf
new file mode 100644 (file)
index 0000000..425bce6
Binary files /dev/null and b/test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf differ
diff --git a/test/shaping/data/text-rendering-tests/tests/GSUB-3.tests b/test/shaping/data/text-rendering-tests/tests/GSUB-3.tests
new file mode 100644 (file)
index 0000000..c2f7e6e
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestGSUBThree.ttf::U+006C,U+006F,U+006C:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-1.tests b/test/shaping/data/text-rendering-tests/tests/MORX-1.tests
new file mode 100644 (file)
index 0000000..794b01b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXOne.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043:[A.alt|B@1000,0|C.alt@2000,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-10.tests b/test/shaping/data/text-rendering-tests/tests/MORX-10.tests
new file mode 100644 (file)
index 0000000..a6a5444
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0041,U+0042,U+0041,U+0042:[A|B@638,0|A@1288,0|B@1926,0|B@2576,0|A@3226,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-11.tests b/test/shaping/data/text-rendering-tests/tests/MORX-11.tests
new file mode 100644 (file)
index 0000000..1fce69b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXEleven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041,U+0042,U+0042,U+0041,U+0041,U+0042,U+0058:[B|A@650,0|B@1288,0|B@1938,0|A@2588,0|X@3226,0|A@3812,0|B@4450,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-12.tests b/test/shaping/data/text-rendering-tests/tests/MORX-12.tests
new file mode 100644 (file)
index 0000000..8b9886f
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/TestMORXTwelve.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0042,U+0043,U+0058,U+0031:[X|C@598,0|A@1230,0|B@1868,0|X@2518,0|one@3116,0]
+../fonts/TestMORXTwelve.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0042,U+0043,U+0058,U+0032:[X|C@598,0|A@1230,0|B@1868,0|X@2518,0|two@3116,0]
+../fonts/TestMORXTwelve.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0042,U+0043,U+0058,U+0033:[X|B@598,0|C@1248,0|A@1880,0|X@2518,0|three@3116,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-13.tests b/test/shaping/data/text-rendering-tests/tests/MORX-13.tests
new file mode 100644 (file)
index 0000000..42d8107
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXThirteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[B|C@626,0|D@1222,0|E@1896,0|A@2452,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-14.tests b/test/shaping/data/text-rendering-tests/tests/MORX-14.tests
new file mode 100644 (file)
index 0000000..d01f2e9
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/TestMORXFourteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[B|C@626,0|D@1222,0|E@1896,0|A@2452,0]
+../fonts/TestMORXFourteen.ttf::U+0041,U+0042,U+0042,U+0042,U+0043,U+0043,U+0043,U+0044,U+0044,U+0044,U+0042,U+0043,U+0044,U+0043,U+0045:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-16.tests b/test/shaping/data/text-rendering-tests/tests/MORX-16.tests
new file mode 100644 (file)
index 0000000..ce0d5b2
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXSixteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[B|C@626,0|D@1222,0|E@1896,0|A@2452,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-17.tests b/test/shaping/data/text-rendering-tests/tests/MORX-17.tests
new file mode 100644 (file)
index 0000000..6e1c94c
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXSeventeen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[B|A@626,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-18.tests b/test/shaping/data/text-rendering-tests/tests/MORX-18.tests
new file mode 100644 (file)
index 0000000..b032a76
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[A|B.alt@639,0|C@1639,0|D.alt1@2235,0|E@3235,0]
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0042,U+0042,U+0044,U+0045:[A|B@639,0|B@1265,0|B.alt@1891,0|D.alt1@2891,0|E@3891,0]
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0044,U+0045:[A|B.alt@639,0|D.alt1@1639,0|E@2639,0]
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0045:[A|B@639,0|E@1265,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-19.tests b/test/shaping/data/text-rendering-tests/tests/MORX-19.tests
new file mode 100644 (file)
index 0000000..e9b9dc4
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0043,U+0044,U+0045:[A.alt|C@1000,0|D.alt1@1596,0|E@2596,0]
+../fonts/TestMORXEighteen.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0044:[D.alt]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-2.tests b/test/shaping/data/text-rendering-tests/tests/MORX-2.tests
new file mode 100644 (file)
index 0000000..3e64d23
--- /dev/null
@@ -0,0 +1,16 @@
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24FF:[O|O@418,0|O@836,0|A@1254,0|B@2084,0|X@2914,0|Y@3744,0|Z@4574,0|C@5404,0|D@6234,0|O@7064,0|O@7482,0|O@7900,0|zero@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+278A:[O|O@418,0|O@836,0|B@1254,0|X@2084,0|Y@2914,0|Z@3744,0|C@4574,0|D@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|one@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+278B:[O|O@418,0|O@836,0|D@1254,0|A@2084,0|B@2914,0|X@3744,0|Y@4574,0|Z@5404,0|C@6234,0|O@7064,0|O@7482,0|O@7900,0|two@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0033:[O|O@418,0|O@836,0|D@1254,0|B@2084,0|X@2914,0|Y@3744,0|Z@4574,0|C@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|three@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0034:[O|O@418,0|O@836,0|X@1254,0|Y@2084,0|Z@2914,0|C@3744,0|D@4574,0|A@5404,0|B@6234,0|O@7064,0|O@7482,0|O@7900,0|four@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0035:[O|O@418,0|O@836,0|X@1254,0|Y@2084,0|Z@2914,0|C@3744,0|D@4574,0|B@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|five@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0036:[O|O@418,0|O@836,0|C@1254,0|D@2084,0|A@2914,0|B@3744,0|X@4574,0|Y@5404,0|Z@6234,0|O@7064,0|O@7482,0|O@7900,0|six@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0037:[O|O@418,0|O@836,0|D@1254,0|C@2084,0|A@2914,0|B@3744,0|X@4574,0|Y@5404,0|Z@6234,0|O@7064,0|O@7482,0|O@7900,0|seven@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0038:[O|O@418,0|O@836,0|C@1254,0|D@2084,0|B@2914,0|X@3744,0|Y@4574,0|Z@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|eight@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+0039:[O|O@418,0|O@836,0|D@1254,0|C@2084,0|B@2914,0|X@3744,0|Y@4574,0|Z@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|nine@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+2793:[O|O@418,0|O@836,0|D@1254,0|X@2084,0|Y@2914,0|Z@3744,0|C@4574,0|A@5404,0|B@6234,0|O@7064,0|O@7482,0|O@7900,0|one_zero@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24EB:[O|O@418,0|O@836,0|D@1254,0|X@2084,0|Y@2914,0|Z@3744,0|C@4574,0|B@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|one_one@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24EC:[O|O@418,0|O@836,0|C@1254,0|D@2084,0|X@2914,0|Y@3744,0|Z@4574,0|A@5404,0|B@6234,0|O@7064,0|O@7482,0|O@7900,0|one_two@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24ED:[O|O@418,0|O@836,0|C@1254,0|D@2084,0|X@2914,0|Y@3744,0|Z@4574,0|B@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|one_three@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24EE:[O|O@418,0|O@836,0|D@1254,0|C@2084,0|X@2914,0|Y@3744,0|Z@4574,0|A@5404,0|B@6234,0|O@7064,0|O@7482,0|O@7900,0|one_four@8318,0]
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0058,U+0059,U+005A,U+0043,U+0044,U+004F,U+004F,U+004F,U+24EF:[O|O@418,0|O@836,0|D@1254,0|C@2084,0|X@2914,0|Y@3744,0|Z@4574,0|B@5404,0|A@6234,0|O@7064,0|O@7482,0|O@7900,0|one_five@8318,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-20.tests b/test/shaping/data/text-rendering-tests/tests/MORX-20.tests
new file mode 100644 (file)
index 0000000..8d04192
--- /dev/null
@@ -0,0 +1,7 @@
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[A|B@639,0|C.alt@1265,0|D@2265,0|E.alt1@2939,0]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043:[A|B@639,0|C.alt@1265,0]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0045:[A|B.alt@639,0|E.alt1@1639,0]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045:[A.alt|E.alt1@1000,0]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0045,U+0045:[E|E@556,0]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[A.alt]
+../fonts/TestMORXTwenty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0045:[E]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-21.tests b/test/shaping/data/text-rendering-tests/tests/MORX-21.tests
new file mode 100644 (file)
index 0000000..a608755
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwentyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[A|B.alt@639,0|C@1639,0|D@2235,0|E@2909,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-22.tests b/test/shaping/data/text-rendering-tests/tests/MORX-22.tests
new file mode 100644 (file)
index 0000000..960874c
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwentytwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[C]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-23.tests b/test/shaping/data/text-rendering-tests/tests/MORX-23.tests
new file mode 100644 (file)
index 0000000..9575a80
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwentythree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[E|E@556,0|E@1112,0|E@1668,0|E@2224,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-24.tests b/test/shaping/data/text-rendering-tests/tests/MORX-24.tests
new file mode 100644 (file)
index 0000000..79a3d7b
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwentyfour.ttf::U+0041,U+0042,U+0043,U+0044,U+0045:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-25.tests b/test/shaping/data/text-rendering-tests/tests/MORX-25.tests
new file mode 100644 (file)
index 0000000..ccd0563
--- /dev/null
@@ -0,0 +1,9 @@
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[A.alt|B.alt@1000,0|C.alt@2000,0|D.alt@3000,0|E.alt@4000,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0045,U+0042,U+0043,U+0044,U+0041:[E|B@556,0|C@1182,0|D@1778,0|A@2452,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0043,U+0042,U+0041,U+0042,U+0043:[C|B@596,0|A.alt@1222,0|B.alt@2222,0|C.alt@3222,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043:[A.alt|B.alt@1000,0|C.alt@2000,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0043,U+0042,U+0041:[C|B@596,0|A@1222,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A.alt|B.alt@1000,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041:[B|A@626,0]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[A]
+../fonts/TestMORXTwentyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042:[B]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-26.tests b/test/shaping/data/text-rendering-tests/tests/MORX-26.tests
new file mode 100644 (file)
index 0000000..bebae60
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/TestMORXTwentysix.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A|B@639,0]
+../fonts/TestMORXTwentysix.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042:[B.alt]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-27.tests b/test/shaping/data/text-rendering-tests/tests/MORX-27.tests
new file mode 100644 (file)
index 0000000..1ec96a2
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/TestMORXTwentyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045,U+0042:[A_E_B]
+../fonts/TestMORXTwentyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045,U+0043:[A_E_C]
+../fonts/TestMORXTwentyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045,U+0044:[A_E_D]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-28.tests b/test/shaping/data/text-rendering-tests/tests/MORX-28.tests
new file mode 100644 (file)
index 0000000..59f5d25
--- /dev/null
@@ -0,0 +1,5 @@
+../fonts/TestMORXTwentyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045,U+0044:[A_E_D]
+../fonts/TestMORXTwentyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0078,U+0045,U+0044:[A_E_D|x@1394,0]
+../fonts/TestMORXTwentyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0045,U+0079,U+0044:[A_E_D|y@1394,0]
+../fonts/TestMORXTwentyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0078,U+0045,U+0079,U+0044:[A_E_D|x@1394,0|y@1923,0]
+../fonts/TestMORXTwentyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0078,U+0078,U+0078,U+0045,U+0079,U+0079,U+0079,U+0044:[A_E_D|x@1394,0|x@1923,0|x@2452,0|y@2981,0|y@3491,0|y@4001,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-29.tests b/test/shaping/data/text-rendering-tests/tests/MORX-29.tests
new file mode 100644 (file)
index 0000000..82fd963
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+004D,U+004D,U+0059,U+0059,U+0041,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|M@1880,0|X@2710,0|X@3074,0|M@3438,0|I@4268,0|N@5098,0|S@5928,0|M@6758,0|Y@7588,0|Y@7920,0|A@8252,0|Z@9082,0|Z@9404,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+004D,U+004D,U+0059,U+0059,U+0042,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|M@1880,0|X@2710,0|X@3074,0|M@3438,0|M@4268,0|I@5098,0|N@5928,0|S@6758,0|Y@7588,0|Y@7920,0|B@8252,0|Z@9082,0|Z@9404,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+004D,U+004D,U+0059,U+0059,U+0043,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|M@1880,0|X@2710,0|X@3074,0|M@3438,0|M@4268,0|Y@5098,0|Y@5430,0|I@5762,0|N@6592,0|S@7422,0|C@8252,0|Z@9082,0|Z@9404,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+004D,U+004D,U+0059,U+0059,U+0044,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|M@1880,0|X@2710,0|X@3074,0|M@3438,0|M@4268,0|Y@5098,0|Y@5430,0|D@5762,0|I@6592,0|N@7422,0|S@8252,0|Z@9082,0|Z@9404,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-3.tests b/test/shaping/data/text-rendering-tests/tests/MORX-3.tests
new file mode 100644 (file)
index 0000000..fc7fe94
--- /dev/null
@@ -0,0 +1,16 @@
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0030:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|zero@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0031:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0032:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|two@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0033:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|three@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0034:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|four@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0035:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|five@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0036:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|six@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0037:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|seven@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0038:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|eight@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+0039:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|nine@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+2793:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_zero@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+24EB:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_one@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+24EC:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_two@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+24ED:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_three@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+24EE:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_four@1793,0]
+../fonts/TestMORXThree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0043,U+0044,U+24EF:[A|B@363,0|X@722,0|C@1086,0|D@1402,0|one_five@1793,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-30.tests b/test/shaping/data/text-rendering-tests/tests/MORX-30.tests
new file mode 100644 (file)
index 0000000..ad4ab21
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+0058,U+0041,U+0059,U+0059,U+0041,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|I@1880,0|N@2710,0|S@3540,0|I@4370,0|N@5200,0|S@6030,0|M@6860,0|X@7690,0|X@8054,0|X@8418,0|A@8782,0|Y@9612,0|Y@9944,0|A@10276,0|Z@11106,0|Z@11428,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+0058,U+0041,U+0059,U+0059,U+0042,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|I@1880,0|I@2710,0|N@3540,0|S@4370,0|N@5200,0|S@6030,0|M@6860,0|X@7690,0|X@8054,0|X@8418,0|A@8782,0|Y@9612,0|Y@9944,0|B@10276,0|Z@11106,0|Z@11428,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+0058,U+0042,U+0059,U+0059,U+0041,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|I@1880,0|N@2710,0|S@3540,0|M@4370,0|I@5200,0|N@6030,0|S@6860,0|X@7690,0|X@8054,0|X@8418,0|B@8782,0|Y@9612,0|Y@9944,0|A@10276,0|Z@11106,0|Z@11428,0]
+../fonts/TestMORXTwentynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+004D,U+004D,U+0058,U+0058,U+0058,U+0042,U+0059,U+0059,U+0042,U+005A,U+005A:[P|Q@333,0|R@699,0|M@1050,0|M@1880,0|I@2710,0|N@3540,0|S@4370,0|I@5200,0|N@6030,0|S@6860,0|X@7690,0|X@8054,0|X@8418,0|B@8782,0|Y@9612,0|Y@9944,0|B@10276,0|Z@11106,0|Z@11428,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-31.tests b/test/shaping/data/text-rendering-tests/tests/MORX-31.tests
new file mode 100644 (file)
index 0000000..ac09e27
--- /dev/null
@@ -0,0 +1,8 @@
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0058,U+0041,U+0059,U+0059,U+0041,U+005A,U+005A:[I|N@830,0|I@1660,0|N@2490,0|S@3320,0|S@4150,0|X@4980,0|X@5344,0|A@5708,0|Y@6538,0|Y@6870,0|A@7202,0|Z@8032,0|Z@8354,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0058,U+0041,U+0059,U+0059,U+0042,U+0059,U+0059:[I|N@830,0|S@1660,0|I@2490,0|N@3320,0|S@4150,0|X@4980,0|X@5344,0|A@5708,0|Y@6538,0|Y@6870,0|B@7202,0|Y@8032,0|Y@8364,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0058,U+0042,U+0059,U+0059,U+0041,U+005A,U+005A:[X|I@364,0|I@1194,0|N@2024,0|S@2854,0|N@3684,0|S@4514,0|X@5344,0|B@5708,0|Y@6538,0|Y@6870,0|A@7202,0|Z@8032,0|Z@8354,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0058,U+0042,U+0059,U+0059,U+0042,U+005A,U+005A:[X|I@364,0|N@1194,0|I@2024,0|N@2854,0|S@3684,0|S@4514,0|X@5344,0|B@5708,0|Y@6538,0|Y@6870,0|B@7202,0|Z@8032,0|Z@8354,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004D,U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0041:[I|N@830,0|S@1660,0|M@2490,0|I@3320,0|N@4150,0|S@4980,0|P@5810,0|Q@6143,0|R@6509,0|A@6860,0|X@7690,0|Y@8054,0|Z@8386,0|A@8708,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004D,U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0042:[I|N@830,0|S@1660,0|M@2490,0|P@3320,0|I@3653,0|N@4483,0|S@5313,0|Q@6143,0|R@6509,0|A@6860,0|X@7690,0|Y@8054,0|Z@8386,0|B@8708,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004D,U+0050,U+0051,U+0052,U+0042,U+0058,U+0059,U+005A,U+0041:[M|I@830,0|N@1660,0|S@2490,0|I@3320,0|N@4150,0|S@4980,0|P@5810,0|Q@6143,0|R@6509,0|B@6860,0|X@7690,0|Y@8054,0|Z@8386,0|A@8708,0]
+../fonts/TestMORXThirtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004D,U+0050,U+0051,U+0052,U+0042,U+0058,U+0059,U+005A,U+0042:[M|I@830,0|N@1660,0|S@2490,0|P@3320,0|I@3653,0|N@4483,0|S@5313,0|Q@6143,0|R@6509,0|B@6860,0|X@7690,0|Y@8054,0|Z@8386,0|B@8708,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-32.tests b/test/shaping/data/text-rendering-tests/tests/MORX-32.tests
new file mode 100644 (file)
index 0000000..6f3ae88
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXThirtytwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[I|N@830,0|S@1660,0|A@2490,0]
+../fonts/TestMORXThirtytwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0059:[I|N@830,0|S@1660,0|X@2490,0|A@2854,0|Y@3684,0]
+../fonts/TestMORXThirtytwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042:[B|I@830,0|N@1660,0|S@2490,0]
+../fonts/TestMORXThirtytwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0042,U+0059:[X|I@364,0|N@1194,0|S@2024,0|B@2854,0|Y@3684,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-33.tests b/test/shaping/data/text-rendering-tests/tests/MORX-33.tests
new file mode 100644 (file)
index 0000000..17d080a
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/TestMORXThirtythree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0068,U+0061:[h|a@618,0|h@1179,0|a@1797,0]
+../fonts/TestMORXThirtythree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0068,U+0061,U+0068,U+0061:[h|a@618,0|h@1179,0|a@1797,0|h@2358,0|a@2976,0|h@3537,0|a@4155,0]
+../fonts/TestMORXThirtythree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0061,U+0068:[a|h@561,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-34.tests b/test/shaping/data/text-rendering-tests/tests/MORX-34.tests
new file mode 100644 (file)
index 0000000..8c309df
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXThirtyfour.ttf::U+0068,U+0061:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-35.tests b/test/shaping/data/text-rendering-tests/tests/MORX-35.tests
new file mode 100644 (file)
index 0000000..a033185
--- /dev/null
@@ -0,0 +1,2 @@
+../fonts/TestMORXThirtyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041:[A|B@639,0|C@1265,0|E@1861,0]
+../fonts/TestMORXThirtyfive.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0058,U+0041,U+0059:[X|A@586,0|B@1225,0|C@1851,0|E@2447,0|Y@3003,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-36.tests b/test/shaping/data/text-rendering-tests/tests/MORX-36.tests
new file mode 100644 (file)
index 0000000..6b2340e
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXThirtysix.ttf::U+0041:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-37.tests b/test/shaping/data/text-rendering-tests/tests/MORX-37.tests
new file mode 100644 (file)
index 0000000..f28c5e2
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXThirtyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A.alt|B.alt@1000,0]
+../fonts/TestMORXThirtyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041:[B|A@650,0]
+../fonts/TestMORXThirtyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D0,U+05D1:[uni05D1|uni05D0@542,0]
+../fonts/TestMORXThirtyseven.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D1,U+05D0:[uni05D0.alt|uni05D1.alt@1000,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-38.tests b/test/shaping/data/text-rendering-tests/tests/MORX-38.tests
new file mode 100644 (file)
index 0000000..abefe29
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXThirtyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A.alt|B.alt@1000,0]
+../fonts/TestMORXThirtyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041:[B|A@650,0]
+../fonts/TestMORXThirtyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D0,U+05D1:[uni05D1.alt|uni05D0.alt@1000,0]
+../fonts/TestMORXThirtyeight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D1,U+05D0:[uni05D0|uni05D1@606,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-39.tests b/test/shaping/data/text-rendering-tests/tests/MORX-39.tests
new file mode 100644 (file)
index 0000000..83bfa52
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXThirtynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A|B@639,0]
+../fonts/TestMORXThirtynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041:[B.alt|A.alt@1000,0]
+../fonts/TestMORXThirtynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D0,U+05D1:[uni05D1.alt|uni05D0.alt@1000,0]
+../fonts/TestMORXThirtynine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D1,U+05D0:[uni05D0|uni05D1@606,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-4.tests b/test/shaping/data/text-rendering-tests/tests/MORX-4.tests
new file mode 100644 (file)
index 0000000..cbb1ce8
--- /dev/null
@@ -0,0 +1,15 @@
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0031:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0032:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|two@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0044,U+0058,U+0059,U+005A,U+0033:[P|Q@333,0|R@699,0|D@1050,0|A@1880,0|X@2710,0|Y@3074,0|Z@3406,0|three@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0034:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|four@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0035:[P|Q@333,0|R@699,0|B@1050,0|A@1880,0|X@2710,0|Y@3074,0|Z@3406,0|five@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0036:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|six@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0037:[P|Q@333,0|R@699,0|B@1050,0|A@1880,0|X@2710,0|Y@3074,0|Z@3406,0|seven@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0043,U+0044,U+0058,U+0059,U+005A,U+0038:[P|Q@333,0|R@699,0|C@1050,0|D@1880,0|A@2710,0|X@3540,0|Y@3904,0|Z@4236,0|eight@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0043,U+0044,U+0058,U+0059,U+005A,U+0039:[P|Q@333,0|R@699,0|D@1050,0|C@1880,0|A@2710,0|X@3540,0|Y@3904,0|Z@4236,0|nine@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0044,U+0058,U+0059,U+005A,U+2793:[P|Q@333,0|R@699,0|D@1050,0|A@1880,0|B@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_zero@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0044,U+0058,U+0059,U+005A,U+24EB:[P|Q@333,0|R@699,0|D@1050,0|B@1880,0|A@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_one@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0044,U+0058,U+0059,U+005A,U+24EC:[P|Q@333,0|R@699,0|C@1050,0|D@1880,0|A@2710,0|B@3540,0|X@4370,0|Y@4734,0|Z@5066,0|one_two@5388,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0044,U+0058,U+0059,U+005A,U+24ED:[P|Q@333,0|R@699,0|C@1050,0|D@1880,0|B@2710,0|A@3540,0|X@4370,0|Y@4734,0|Z@5066,0|one_three@5388,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0044,U+0058,U+0059,U+005A,U+24EE:[P|Q@333,0|R@699,0|D@1050,0|C@1880,0|A@2710,0|B@3540,0|X@4370,0|Y@4734,0|Z@5066,0|one_four@5388,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0044,U+0058,U+0059,U+005A,U+24EF:[P|Q@333,0|R@699,0|D@1050,0|C@1880,0|B@2710,0|A@3540,0|X@4370,0|Y@4734,0|Z@5066,0|one_five@5388,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-40.tests b/test/shaping/data/text-rendering-tests/tests/MORX-40.tests
new file mode 100644 (file)
index 0000000..c99155e
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXForty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042:[A|B@639,0]
+../fonts/TestMORXForty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0042,U+0041:[B.alt|A.alt@1000,0]
+../fonts/TestMORXForty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D0,U+05D1:[uni05D1|uni05D0@542,0]
+../fonts/TestMORXForty.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+05D1,U+05D0:[uni05D0.alt|uni05D1.alt@1000,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-41.tests b/test/shaping/data/text-rendering-tests/tests/MORX-41.tests
new file mode 100644 (file)
index 0000000..815bebe
--- /dev/null
@@ -0,0 +1,4 @@
+../fonts/TestMORXFourtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0061,U+0063:[a_c]
+../fonts/TestMORXFourtyone.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0062,U+0063:[b_c]
+../fonts/TestMORXFourtyone.ttf::U+0063,U+0063:*
+../fonts/TestMORXFourtyone.ttf::U+0061,U+0062,U+0063,U+0063:*
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-5.tests b/test/shaping/data/text-rendering-tests/tests/MORX-5.tests
new file mode 100644 (file)
index 0000000..ca8d086
--- /dev/null
@@ -0,0 +1,25 @@
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0033:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|three@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0034:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|four@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0035:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|five@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0036:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|six@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0037:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|seven@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0038:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|eight@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0038:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|eight@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+0039:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|nine@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+0039:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|nine@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+2793:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_zero@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+2793:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_zero@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+24EB:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_one@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+24EB:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_one@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+24EC:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_two@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+24EC:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_two@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0058,U+0059,U+005A,U+24EC:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|C@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_two@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+24ED:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_three@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+24ED:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_three@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0058,U+0059,U+005A,U+24ED:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|C@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_three@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+24EE:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_four@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+24EE:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_four@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0058,U+0059,U+005A,U+24EE:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|C@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_four@4558,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0058,U+0059,U+005A,U+24EF:[P|Q@333,0|R@699,0|A@1050,0|X@1880,0|Y@2244,0|Z@2576,0|one_five@2898,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0058,U+0059,U+005A,U+24EF:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|X@2710,0|Y@3074,0|Z@3406,0|one_five@3728,0]
+../fonts/TestMORXFour.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0050,U+0051,U+0052,U+0041,U+0042,U+0043,U+0058,U+0059,U+005A,U+24EF:[P|Q@333,0|R@699,0|A@1050,0|B@1880,0|C@2710,0|X@3540,0|Y@3904,0|Z@4236,0|one_five@4558,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-6.tests b/test/shaping/data/text-rendering-tests/tests/MORX-6.tests
new file mode 100644 (file)
index 0000000..ff9c061
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+004F,U+004F,U+0041,U+0042,U+0043,U+0044,U+0045,U+0046,U+0047,U+004F,U+004F,U+004F,U+0033,U+0031,U+0034,U+0031:[O|O@418,0|O@836,0|E@1254,0|F@2084,0|A@2914,0|G@3744,0|B@4574,0|C@5404,0|D@6234,0|O@7064,0|O@7482,0|O@7900,0|three@8318,0|one@9168,0|four@10018,0|one@10868,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-7.tests b/test/shaping/data/text-rendering-tests/tests/MORX-7.tests
new file mode 100644 (file)
index 0000000..f250848
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXTwo.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+004F,U+0042,U+0043,U+0044,U+0031:[B|C@830,0|D@1660,0|O@2490,0|one@2908,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-8.tests b/test/shaping/data/text-rendering-tests/tests/MORX-8.tests
new file mode 100644 (file)
index 0000000..aa0d28b
--- /dev/null
@@ -0,0 +1,3 @@
+../fonts/TestMORXEight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0030,U+0041,U+0042,U+0043:[zero|A@914,0|B@1552,0|C@2202,0]
+../fonts/TestMORXEight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0031,U+0041,U+0042,U+0043:[one|B@914,0|C@1564,0|A@2196,0]
+../fonts/TestMORXEight.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0032,U+0041,U+0042,U+0043:[two|C@914,0|A@1546,0|B@2184,0]
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-9.tests b/test/shaping/data/text-rendering-tests/tests/MORX-9.tests
new file mode 100644 (file)
index 0000000..a899908
--- /dev/null
@@ -0,0 +1 @@
+../fonts/TestMORXNine.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0058,U+0041,U+0042:[B|A@650,0|X@1288,0|A@1874,0|B@2512,0]
index 8348dc2..feff70a 100644 (file)
@@ -4,6 +4,10 @@ from __future__ import print_function, division, absolute_import
 
 import sys, os, re, difflib, unicodedata, errno, cgi
 from itertools import *
+try:
+       import unicodedata2 as unicodedata
+except Exception:
+       pass
 
 diff_symbols = "-+=*&^%$#@!~/"
 diff_colors = ['red', 'green', 'blue']
@@ -56,10 +60,10 @@ try:
                                                yield 0x10000 + (high_surrogate - 0xD800) * 0x400 + (cp - 0xDC00)
                                                high_surrogate = None
                                        else:
-                                               yield 0xFFFC
+                                               yield 0xFFFD
                                else:
                                        if high_surrogate:
-                                               yield 0xFFFC
+                                               yield 0xFFFD
                                                high_surrogate = None
                                        if 0xD800 <= cp <= 0xDBFF:
                                                high_surrogate = cp
@@ -67,7 +71,7 @@ try:
                                                yield cp
                                                high_surrogate = None
                        if high_surrogate:
-                               yield 0xFFFC
+                               yield 0xFFFD
 
 except NameError:
        unichr = chr
index 93ebcfc..4ab74f0 100755 (executable)
@@ -3,8 +3,9 @@
 dir=`mktemp -d`
 
 out=/dev/stdout
-if test "x${1:0:3}" == 'x-o='; then
-       out=${1:3}
+if test "x$1" == 'x-o'; then
+       shift
+       out=$1
        shift
 fi
 hb_shape=$1
index 73b61c2..26853e4 100755 (executable)
@@ -2,31 +2,34 @@
 
 from __future__ import print_function, division, absolute_import
 
-import sys, os, subprocess
-
+import sys, os, subprocess, hashlib, tempfile, shutil
 
 def cmd(command):
-       p = subprocess.Popen (
-               command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-       p.wait ()
-       print (p.stderr.read (), end="") # file=sys.stderr
-       return p.stdout.read ().decode ("utf-8").strip (), p.returncode
-
+       global process
+       process.stdin.write ((' '.join (command) + '\n').encode ("utf-8"))
+       process.stdin.flush ()
+       return process.stdout.readline().decode ("utf-8").strip ()
 
 args = sys.argv[1:]
-if not args or sys.argv[1].find('hb-shape') == -1 or not os.path.exists (sys.argv[1]):
+
+reference = False
+if len (args) and args[0] == "--reference":
+       reference = True
+       args = args[1:]
+
+if not args or args[0].find('hb-shape') == -1 or not os.path.exists (args[0]):
        print ("""First argument does not seem to point to usable hb-shape.""")
        sys.exit (1)
 hb_shape, args = args[0], args[1:]
 
-extra_options = "--verify"
+process = subprocess.Popen ([hb_shape, '--batch'],
+                           stdin=subprocess.PIPE,
+                           stdout=subprocess.PIPE,
+                           stderr=sys.stdout)
 
+passes = 0
 fails = 0
-
-reference = False
-if len (args) and args[0] == "--reference":
-       reference = True
-       args = args[1:]
+skips = 0
 
 if not len (args):
        args = ['-']
@@ -44,56 +47,95 @@ for filename in args:
                f = open (filename)
 
        for line in f:
+               comment = False
+               if line.startswith ("#"):
+                       comment = True
+                       line = line[1:]
+
+                       if line.startswith (' '):
+                               if not reference:
+                                       print ("#%s" % line)
+                               continue
+
+               line = line.strip ()
+               if not line:
+                       continue
+
                fontfile, options, unicodes, glyphs_expected = line.split (":")
-               cwd = os.path.dirname(filename)
-               fontfile = os.path.normpath (os.path.join (cwd, fontfile))
+               if fontfile.startswith ('/') or fontfile.startswith ('"/'):
+                       fontfile, expected_hash = fontfile.split('@')
+
+                       try:
+                               with open (fontfile, 'rb') as ff:
+                                       actual_hash = hashlib.sha1 (ff.read()).hexdigest ().strip ()
+                                       if actual_hash != expected_hash:
+                                               print ('different version of %s found; Expected hash %s, got %s; skipping.' %
+                                                          (fontfile, expected_hash, actual_hash))
+                                               skips += 1
+                                               continue
+                       except:
+                               print ('%s not found, skip.' % fontfile)
+                               skips += 1
+                               continue
+               else:
+                       cwd = os.path.dirname(filename)
+                       fontfile = os.path.normpath (os.path.join (cwd, fontfile))
 
-               if line.startswith ("#"):
+               extra_options = ["--shaper=ot"]
+               if glyphs_expected != '*':
+                       extra_options.append("--verify")
+
+               if comment:
                        if not reference:
-                               print ("# %s %s --unicodes %s" % (hb_shape, fontfile, unicodes))
+                               print ('# %s "%s" --unicodes %s' % (hb_shape, fontfile, unicodes))
                        continue
 
                if not reference:
-                       print ("%s %s %s %s --unicodes %s" %
-                                        (hb_shape, fontfile, extra_options, options, unicodes))
-
-               glyphs1, returncode = cmd ([hb_shape, "--font-funcs=ft",
-                       fontfile, extra_options, "--unicodes",
-                       unicodes] + (options.split (' ') if options else []))
+                       print ('%s "%s" %s %s --unicodes %s' %
+                                        (hb_shape, fontfile, ' '.join(extra_options), options, unicodes))
 
-               if returncode:
-                       print ("hb-shape --font-funcs=ft failed.") # file=sys.stderr
-                       fails = fails + 1
-                       #continue
+               # hack to support fonts with space on run-tests.py, after several other tries...
+               if ' ' in fontfile:
+                       new_fontfile = os.path.join (tempfile.gettempdir (), 'tmpfile')
+                       shutil.copyfile(fontfile, new_fontfile)
+                       fontfile = new_fontfile
 
-               glyphs2, returncode = cmd ([hb_shape, "--font-funcs=ot",
-                       fontfile, extra_options, "--unicodes",
+               glyphs1 = cmd ([hb_shape, "--font-funcs=ft",
+                       fontfile] + extra_options + ["--unicodes",
                        unicodes] + (options.split (' ') if options else []))
 
-               if returncode:
-                       print ("ERROR: hb-shape --font-funcs=ot failed.") # file=sys.stderr
-                       fails = fails + 1
-                       #continue
+               glyphs2 = cmd ([hb_shape, "--font-funcs=ot",
+                       fontfile] + extra_options + ["--unicodes",
+                       unicodes] + (options.split (' ') if options else []))
 
-               if glyphs1 != glyphs2:
+               if glyphs1 != glyphs2 and glyphs_expected != '*':
                        print ("FT funcs: " + glyphs1) # file=sys.stderr
                        print ("OT funcs: " + glyphs2) # file=sys.stderr
-                       fails = fails + 1
+                       fails += 1
+               else:
+                       passes += 1
 
                if reference:
                        print (":".join ([fontfile, options, unicodes, glyphs1]))
                        continue
 
-               if glyphs1.strip() != glyphs_expected.strip():
+               if glyphs1.strip() != glyphs_expected and glyphs_expected != '*':
                        print ("Actual:   " + glyphs1) # file=sys.stderr
                        print ("Expected: " + glyphs_expected) # file=sys.stderr
-                       fails = fails + 1
+                       fails += 1
+               else:
+                       passes += 1
 
-if fails != 0:
-       if not reference:
-               print (str (fails) + " tests failed.") # file=sys.stderr
-       sys.exit (1)
+if not reference:
+       print ("%d tests passed; %d failed; %d skipped." % (passes, fails, skips)) # file=sys.stderr
+       if not (fails + passes):
+               print ("No tests ran.")
+       elif not (fails + skips):
+               print ("All tests passed.")
 
+if fails:
+       sys.exit (1)
+elif passes:
+       sys.exit (0)
 else:
-       if not reference:
-               print ("All tests passed.")
+       sys.exit (77)
diff --git a/test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-letters.txt
new file mode 100644 (file)
index 0000000..f09dbc8
--- /dev/null
@@ -0,0 +1,3 @@
+আ অা
+ৠ ঋৃ
+ৡ ঌৢ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt
new file mode 100644 (file)
index 0000000..4265436
--- /dev/null
@@ -0,0 +1,33 @@
+ख ख्ा ख्‍ा
+ग ग्ा ग्‍ा
+घ घ्ा घ्‍ा
+च च्ा च्‍ा
+ज ज्ा ज्‍ा
+झ झ्ा झ्‍ा
+ञ ञ्ा ञ्‍ा
+ण ण्ा ण्‍ा
+त त्ा त्‍ा
+थ थ्ा थ्‍ा
+ध ध्ा ध्‍ा
+न न्ा न्‍ा
+ऩ ऩ्ा ऩ्‍ा ऩ्ा ऩ्‍ा
+प प्ा प्‍ा
+ब ब्ा ब्‍ा
+भ भ्ा भ्‍ा
+म म्ा म्‍ा
+य य्ा य्‍ा
+ल ल्ा ल्‍ा
+व व्ा व्‍ा
+श श्ा श्‍ा
+ष ष्ा ष्‍ा
+स स्ा स्‍ा
+ख़ ख़्ा ख़्‍ा ख़्ा ख़्‍ा
+ग़ ग़्ा ग़्‍ा ग़्ा ग़्‍ा
+ज़ ज़्ा ज़्‍ा ज़्ा ज़्‍ा
+य़ य़्ा य़्‍ा य़्ा य़्‍ा
+ॹ ॹ्ा ॹ्‍ा
+ॺ ॺ्ा ॺ्‍ा
+ज़ ॻ्ा ॻ्‍ा
+ॼ ॼ्ा ॼ्‍ा
+ॾ ॾ्ा ॾ्‍ा
+ॿ ॿ्ा ॿ्‍ा
diff --git a/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt
new file mode 100644 (file)
index 0000000..5a41252
--- /dev/null
@@ -0,0 +1,17 @@
+ऄ अॆ
+आ अा
+ई र्इ
+ऊ उु
+ऍ एॅ
+ऎ एॆ
+ऐ एे
+ऑ अॉ आॅ
+ऒ अॊ आॆ
+ओ अो आे
+औ अौ आै
+ॲ अॅ
+ॳ अऺ
+ॴ अऻ आऺ
+ॵ अॏ
+ॶ अॖ
+ॷ अॗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letters.txt
new file mode 100644 (file)
index 0000000..add4332
--- /dev/null
@@ -0,0 +1,8 @@
+આ અા
+ઍ અૅ
+એ અે
+ઐ અૈ
+ઑ અૉ
+ઓ અો અાૅ
+ઔ અૌ અાૈ
+ૉ ૅા
diff --git a/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt
new file mode 100644 (file)
index 0000000..b2adaab
--- /dev/null
@@ -0,0 +1,9 @@
+ਆ ਅਾ
+ਇ ੲਿ
+ਈ ੲੀ
+ਉ ੳੁ
+ਊ ੳੂ
+ਏ ੲੇ
+ਐ ਅੈ
+ਓ ੳੋ
+ਔ ਅੌ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt
new file mode 100644 (file)
index 0000000..cc05db9
--- /dev/null
@@ -0,0 +1,3 @@
+ಊ ಉಾ
+ಔ ಒೌ
+ೠ ಋಾ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt
new file mode 100644 (file)
index 0000000..061c642
--- /dev/null
@@ -0,0 +1,5 @@
+ഈ ഇൗ
+ഊ ഉൗ
+ഐ എെ
+ഓ ഒാ
+ഔ ഒൗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt
new file mode 100644 (file)
index 0000000..e8d24cb
--- /dev/null
@@ -0,0 +1,3 @@
+ଆ ଅା
+ଐ ଏୗ
+ଔ ଓୗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt
new file mode 100644 (file)
index 0000000..c3cfc84
--- /dev/null
@@ -0,0 +1,5 @@
+ఓ ఒౕ
+ఔ ఒౌ
+ీ ిౕ
+ే ెౕ
+ో ొౕ
diff --git a/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt b/test/shaping/texts/in-house/shaper-indic/south-east-asian/script-khmer/misc/misc.txt
deleted file mode 100644 (file)
index 945dd1d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-ខ្មែ
-ជា
-ថ្ងៃ
-មា
-ម្ពុ
-រ
-រី
-រ៍
-សៅ
-រ្ឥ
-ងឹ្ឈ
-ង្ឈឹ
-ង្គ្រ
-ង្រ្គ
-ម៉្លេះ
-ម‌៉្លេះ
-ប៊័
-នែ៎
-កេ្រ
-កៀ្រ
-កោ្រ
-កៅ្រ
-ព៑ា
diff --git a/test/shaping/texts/in-house/shaper-khmer/misc.txt b/test/shaping/texts/in-house/shaper-khmer/misc.txt
new file mode 100644 (file)
index 0000000..3bbffe7
--- /dev/null
@@ -0,0 +1,89 @@
+ខ្មែ
+ជា
+ថ្ងៃ
+មា
+ម្ពុ
+រ
+រី
+រ៍
+សៅ
+រ្ឥ
+ងឹ្ឈ
+ង្ឈឹ
+ង្គ្រ
+ង្រ្គ
+ម៉្លេះ
+ម‌៉្លេះ
+ប៊័
+នែ៎
+កេ្រ
+កៀ្រ
+កោ្រ
+កៅ្រ
+ព៑ា
+កន្ត្រាក់
+កន្រ្សិក់
+កន្រ្សីក់
+ក្សាន្ត
+ក្សិន្ត
+ក្សីន្ត
+ក្សឹន្ត
+ក្សឺន្ត
+ក្សុន្ត
+ក្សូន្ត
+ក្សួន្ត
+ក្សឿន្ត
+ឃ្ល្សាំ
+ឃ្ល្សិះ
+ឃ្ល្សុំ
+ឃ្ល្សុះ
+ឃ្ល្សេះ
+ឃ្ល្សោះ
+ឃ្ល្សំ
+ឃ្ល្សះ
+ញូ
+ញ្ញ
+ញ្ញុ
+ញ្ញូ
+ញ្ញួ
+ត្រ្សៀ
+ត្រ្សេ
+ត្រ្សែ
+ត្រ្សៃ
+ត្រ្សោ
+ត្រ្សៅ
+ធ្លុំក់
+ធ្លោក់
+ធ្លៅក់
+ធ្លំក់
+ម្ត្ល៉ា
+ម្ត្ល៉ុ
+ម្ត្ល៉ឿ
+ម្ត្ល៉ៀ
+យ្យើហ្វ្លៃ
+រ្រ
+សាស្ត្រឃ្ឈងា
+សាស្ត្រឃ្ឈងិ
+សាស្ត្រឃ្ឈងី
+ស្ត្រីវ័ខ្ញ្សា
+ស្រ្តា
+ស្រ្តិ
+ស្រ្តី
+ស្រ្តឹ
+ស្រ្តឺ
+ស្រ្តុ
+ស្រ្តូ
+ស្រ្តួ
+ស្រ្តើ
+ស្រ្តឿ
+ស្រ្ត៊ឿ
+ស្រ្ត៊ៀ
+ស្រ្ត៊េ
+ស្រ្ត៊ែ
+ស្រ្ត៊ៃ
+ស្រ្ត៊ំ
+ហ្គ្ស៊ើ
+ហ្គ្ស៊ឿ
+ហ្គ្ស៊ៀ
+ហ្រ្វង្ក
+ហ្រ្វាំង
index 336d33d..1673cfb 100644 (file)
@@ -7,7 +7,7 @@ SUBDIRS = data
 
 # Convenience targets:
 lib:
-       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 EXTRA_DIST += \
        CMakeLists.txt \
index 95ab828..71f7a82 100644 (file)
@@ -96,8 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -304,6 +303,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -691,7 +692,7 @@ uninstall-am:
 
 # Convenience targets:
 lib:
-       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 -include $(top_srcdir)/git.mk
 
index 0d1b2f0..0677120 100644 (file)
@@ -5,7 +5,7 @@ EXTRA_DIST =
 CLEANFILES =
 SUBDIRS =
 
-EXTRA_DIST = \
+EXTRA_DIST += \
        $(TESTS) \
        expected/basics \
        expected/full-font \
index 0988d97..957bb34 100644 (file)
@@ -99,8 +99,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -509,6 +508,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -578,15 +579,8 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 NULL = 
-EXTRA_DIST = \
-       $(TESTS) \
-       expected/basics \
-       expected/full-font \
-       expected/japanese \
-       fonts \
-       profiles \
-       $(NULL)
-
+EXTRA_DIST = $(TESTS) expected/basics expected/full-font \
+       expected/japanese fonts profiles $(NULL)
 CLEANFILES = 
 SUBDIRS = 
 TEST_EXTENSIONS = .tests
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf
new file mode 100644 (file)
index 0000000..1bd287d
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.default.61,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.61,62,63.otf
new file mode 100644 (file)
index 0000000..328c6ee
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.61,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf
new file mode 100644 (file)
index 0000000..4602847
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf
new file mode 100644 (file)
index 0000000..18a9bcc
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf
new file mode 100644 (file)
index 0000000..edd389b
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf
new file mode 100644 (file)
index 0000000..65fa1da
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf
new file mode 100644 (file)
index 0000000..53109e2
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf
new file mode 100644 (file)
index 0000000..dd908c2
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf
new file mode 100644 (file)
index 0000000..5422d32
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.1FC,21,41,20,62,63.otf
new file mode 100644 (file)
index 0000000..604e140
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.1FC,21,41,20,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.61,62,63.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.61,62,63.otf
new file mode 100644 (file)
index 0000000..a0b2c2f
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.61,62,63.otf differ
diff --git a/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.D7,D8,D9,DA,DE.otf
new file mode 100644 (file)
index 0000000..8055328
Binary files /dev/null and b/test/subset/data/expected/full-font/SourceSansPro-Regular.drop-hints.desubroutinize.D7,D8,D9,DA,DE.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,3048,304A,304B.otf
new file mode 100644 (file)
index 0000000..8d717cc
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,3048,304A,304B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf
new file mode 100644 (file)
index 0000000..3d570cd
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.3042,3044,3046,73E0,5EA6,8F38.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.default.61,63,65,6B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.61,63,65,6B.otf
new file mode 100644 (file)
index 0000000..216ed17
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.61,63,65,6B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf
new file mode 100644 (file)
index 0000000..f548f48
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E.otf
new file mode 100644 (file)
index 0000000..6362d21
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.default.660E.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize..otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize..otf
new file mode 100644 (file)
index 0000000..7c0c5fd
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize..otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,3048,304A,304B.otf
new file mode 100644 (file)
index 0000000..e51866a
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,3048,304A,304B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf
new file mode 100644 (file)
index 0000000..c4f6bb2
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.61,63,65,6B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.61,63,65,6B.otf
new file mode 100644 (file)
index 0000000..62ddb60
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.61,63,65,6B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf
new file mode 100644 (file)
index 0000000..7ce9d40
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E.otf
new file mode 100644 (file)
index 0000000..35d9eea
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.desubroutinize.660E.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,3048,304A,304B.otf
new file mode 100644 (file)
index 0000000..9e1041d
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,3048,304A,304B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf
new file mode 100644 (file)
index 0000000..6a3bff1
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.61,63,65,6B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.61,63,65,6B.otf
new file mode 100644 (file)
index 0000000..06d28b6
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.61,63,65,6B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf
new file mode 100644 (file)
index 0000000..ce9d287
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E.otf
new file mode 100644 (file)
index 0000000..27c4676
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.660E.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize..otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize..otf
new file mode 100644 (file)
index 0000000..a73617a
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize..otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,3048,304A,304B.otf
new file mode 100644 (file)
index 0000000..790b714
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,3048,304A,304B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf
new file mode 100644 (file)
index 0000000..c707bcd
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.61,63,65,6B.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.61,63,65,6B.otf
new file mode 100644 (file)
index 0000000..591d139
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.61,63,65,6B.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf
new file mode 100644 (file)
index 0000000..efc98b6
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf differ
diff --git a/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E.otf b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E.otf
new file mode 100644 (file)
index 0000000..27c4676
Binary files /dev/null and b/test/subset/data/expected/japanese/SourceHanSans-Regular.drop-hints.desubroutinize.660E.otf differ
diff --git a/test/subset/data/fonts/SourceHanSans-Regular.otf b/test/subset/data/fonts/SourceHanSans-Regular.otf
new file mode 100755 (executable)
index 0000000..dd807db
Binary files /dev/null and b/test/subset/data/fonts/SourceHanSans-Regular.otf differ
diff --git a/test/subset/data/fonts/SourceSansPro-Regular.otf b/test/subset/data/fonts/SourceSansPro-Regular.otf
new file mode 100644 (file)
index 0000000..279e691
Binary files /dev/null and b/test/subset/data/fonts/SourceSansPro-Regular.otf differ
diff --git a/test/subset/data/profiles/desubroutinize.txt b/test/subset/data/profiles/desubroutinize.txt
new file mode 100644 (file)
index 0000000..67f3a84
--- /dev/null
@@ -0,0 +1 @@
+--desubroutinize
diff --git a/test/subset/data/profiles/drop-hints-desubroutinize.txt b/test/subset/data/profiles/drop-hints-desubroutinize.txt
new file mode 100644 (file)
index 0000000..279d466
--- /dev/null
@@ -0,0 +1,2 @@
+--no-hinting
+--desubroutinize
index ff195ce..f422ff5 100644 (file)
@@ -1,5 +1,6 @@
 FONTS:
 Roboto-Regular.ttf
+SourceSansPro-Regular.otf
 
 PROFILES:
 default.txt
index 5a04380..fc58646 100644 (file)
@@ -1,5 +1,6 @@
 FONTS:
 Mplus1p-Regular.ttf
+SourceHanSans-Regular.otf
 
 PROFILES:
 default.txt
index 1cd1a19..fb4684c 100755 (executable)
@@ -15,90 +15,108 @@ import tempfile
 
 from subset_test_suite import SubsetTestSuite
 
+# https://stackoverflow.com/a/377028
+def which(program):
+       def is_exe(fpath):
+               return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+       fpath, _ = os.path.split(program)
+       if fpath:
+               if is_exe(program):
+                       return program
+       else:
+               for path in os.environ["PATH"].split(os.pathsep):
+                       exe_file = os.path.join(path, program)
+                       if is_exe(exe_file):
+                               return exe_file
+
+       return None
+
+ttx = which ("ttx")
+ots_sanitize = which ("ots-sanitize")
+
+if not ttx:
+       print("TTX is not present, skipping test.")
+       sys.exit (77)
 
 def cmd(command):
        p = subprocess.Popen (
                command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-       (stdoutdata, stderrdata) = p.communicate()
+       (stdoutdata, stderrdata) = p.communicate ()
        print (stderrdata, end="") # file=sys.stderr
        return stdoutdata, p.returncode
 
-def read_binary(file_path):
-       with open(file_path, 'rb') as f:
-               return f.read()
+def read_binary (file_path):
+       with open (file_path, 'rb') as f:
+               return f.read ()
 
 def fail_test(test, cli_args, message):
        print ('ERROR: %s' % message)
        print ('Test State:')
-       print ('  test.font_path    %s' % os.path.abspath(test.font_path))
-       print ('  test.profile_path %s' % os.path.abspath(test.profile_path))
-       print ('  test.unicodes     %s' % test.unicodes())
-       expected_file = os.path.join(test_suite.get_output_directory(),
-                                    test.get_font_name())
-       print ('  expected_file     %s' % os.path.abspath(expected_file))
+       print ('  test.font_path    %s' % os.path.abspath (test.font_path))
+       print ('  test.profile_path %s' % os.path.abspath (test.profile_path))
+       print ('  test.unicodes     %s' % test.unicodes ())
+       expected_file = os.path.join(test_suite.get_output_directory (),
+                                    test.get_font_name ())
+       print ('  expected_file     %s' % os.path.abspath (expected_file))
        return 1
 
 def run_test(test, should_check_ots):
-       out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
+       out_file = os.path.join(tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ())
        cli_args = [hb_subset,
                    "--font-file=" + test.font_path,
                    "--output-file=" + out_file,
-                   "--unicodes=%s" % test.unicodes()]
-       cli_args.extend (test.get_profile_flags())
-       print (' '.join(cli_args))
-       _, return_code = cmd(cli_args)
+                   "--unicodes=%s" % test.unicodes ()]
+       cli_args.extend (test.get_profile_flags ())
+       print (' '.join (cli_args))
+       _, return_code = cmd (cli_args)
 
        if return_code:
-               return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))
+               return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code))
 
-       expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
-                                           test.get_font_name()))
+       expected_ttx, return_code = run_ttx (os.path.join (test_suite.get_output_directory (),
+                                           test.get_font_name ()))
        if return_code:
-               return fail_test(test, cli_args, "ttx (expected) returned %d" % (return_code))
+               return fail_test (test, cli_args, "ttx (expected) returned %d" % (return_code))
 
        actual_ttx, return_code = run_ttx(out_file)
        if return_code:
-               return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code))
+               return fail_test (test, cli_args, "ttx (actual) returned %d" % (return_code))
 
        print ("stripping checksums.")
        expected_ttx = strip_check_sum (expected_ttx)
        actual_ttx = strip_check_sum (actual_ttx)
 
        if not actual_ttx == expected_ttx:
-               for line in unified_diff(expected_ttx.splitlines(1), actual_ttx.splitlines(1)):
-                       sys.stdout.write(line)
-               sys.stdout.flush()
+               for line in unified_diff (expected_ttx.splitlines (1), actual_ttx.splitlines (1)):
+                       sys.stdout.write (line)
+               sys.stdout.flush ()
                return fail_test(test, cli_args, 'ttx for expected and actual does not match.')
 
        if should_check_ots:
                print ("Checking output with ots-sanitize.")
-               if not check_ots(out_file):
-                       return fail_test(test, cli_args, 'ots for subsetted file fails.')
+               if not check_ots (out_file):
+                       return fail_test (test, cli_args, 'ots for subsetted file fails.')
 
        return 0
 
-def run_ttx(file):
+def run_ttx (file):
        print ("ttx %s" % file)
-       cli_args = ["ttx",
-                   "-q",
-                   "-o-",
-                   file]
-       return cmd(cli_args)
+       return cmd([ttx, "-q", "-o-", file])
 
 def strip_check_sum (ttx_string):
        return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
                       'checkSumAdjustment value="0x00000000"',
-                      ttx_string.decode (), count=1)
+                      ttx_string.decode ("utf-8"), count=1)
 
 def has_ots ():
-       _, returncode = cmd(["which", "ots-sanitize"])
-       if returncode:
+       if not ots_sanitize:
                print("OTS is not present, skipping all ots checks.")
                return False
        return True
 
 def check_ots (path):
-       ots_report, returncode = cmd(["ots-sanitize", path])
+       ots_report, returncode = cmd ([ots_sanitize, path])
        if returncode:
                print("OTS Failure: %s" % ots_report);
                return False
@@ -110,24 +128,19 @@ if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.ar
        sys.exit (1)
 hb_subset, args = args[0], args[1:]
 
-if not len(args):
+if not len (args):
        print ("No tests supplied.")
        sys.exit (1)
 
-_, returncode = cmd(["which", "ttx"])
-if returncode:
-       print("TTX is not present, skipping test.")
-       sys.exit (77)
-
 has_ots = has_ots()
 
 fails = 0
 for path in args:
-       with io.open(path, mode="r", encoding="utf-8") as f:
+       with io.open (path, mode="r", encoding="utf-8") as f:
                print ("Running tests in " + path)
-               test_suite = SubsetTestSuite(path, f.read())
-               for test in test_suite.tests():
-                       fails += run_test(test, has_ots)
+               test_suite = SubsetTestSuite (path, f.read())
+               for test in test_suite.tests ():
+                       fails += run_test (test, has_ots)
 
 if fails != 0:
        print (str (fails) + " test(s) failed.")
index 3538650..5e3368e 100644 (file)
@@ -28,6 +28,14 @@ class Test:
                                       self.unicodes(),
                                       font_base_name_parts[1])
 
+       def get_font_extension(self):
+               font_base_name = os.path.basename(self.font_path)
+               font_base_name_parts = os.path.splitext(font_base_name)
+               return font_base_name_parts[1]
+
+       def applicable(self):
+               return self.profile_path.find("desubroutinize") < 0 or self.get_font_extension() == "otf"
+
 # A group of tests to perform on the subsetter. Each test
 # Identifies a font a subsetting profile, and a subset to be cut.
 class SubsetTestSuite:
@@ -47,7 +55,7 @@ class SubsetTestSuite:
                if not os.path.exists(output_dir):
                        os.mkdir(output_dir)
                if not os.path.isdir(output_dir):
-                       raise Error("%s is not a directory." % output_dir)
+                       raise Exception("%s is not a directory." % output_dir)
 
                return output_dir
 
@@ -57,7 +65,9 @@ class SubsetTestSuite:
                        for profile in self.profiles:
                                profile = os.path.join(self._base_path(), "profiles", profile)
                                for subset in self.subsets:
-                                       yield Test(font, profile, subset)
+                                       test = Test(font, profile, subset)
+                                       if test.applicable():
+                                               yield test
 
        def _base_path(self):
                return os.path.dirname(os.path.dirname(self.test_path))
index d4ab9cd..e24a6f3 100644 (file)
@@ -11,6 +11,8 @@ include Makefile.sources
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
 bin_PROGRAMS =
 
@@ -47,17 +49,16 @@ hb_shape_SOURCES = $(HB_SHAPE_sources)
 bin_PROGRAMS += hb-shape
 
 hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
-hb_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+hb_subset_LDADD = \
+       $(LDADD) \
+       $(top_builddir)/src/libharfbuzz-subset.la
 bin_PROGRAMS += hb-subset
 
-if HAVE_OT
 hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
 bin_PROGRAMS += hb-ot-shape-closure
-endif # HAVE_OT
 
 endif # HAVE_GLIB
 
-#if HAVE_OT
 #if HAVE_FONTCONFIG
 #hb_fc_list_SOURCES = \
 #      hb-fc.cc \
@@ -70,6 +71,5 @@ endif # HAVE_GLIB
 #      $(NULL)
 #bin_PROGRAMS += hb-fc-list
 #endif # HAVE_FONTCONFIG
-#endif # HAVE_OT
 
 -include $(top_srcdir)/git.mk
index 86678cf..820a5a8 100644 (file)
@@ -90,10 +90,9 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
 @HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__append_1 = hb-view
-@HAVE_GLIB_TRUE@am__append_2 = hb-shape hb-subset
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__append_3 = hb-ot-shape-closure
+@HAVE_GLIB_TRUE@am__append_2 = hb-shape hb-subset hb-ot-shape-closure
 subdir = util
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
@@ -101,8 +100,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_link_flag.m4 \
        $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
        $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
        $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-       $(top_srcdir)/configure.ac
+       $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@@ -111,9 +109,8 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 @HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__EXEEXT_1 = hb-view$(EXEEXT)
-@HAVE_GLIB_TRUE@am__EXEEXT_2 = hb-shape$(EXEEXT) hb-subset$(EXEEXT)
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__EXEEXT_3 =  \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ hb-ot-shape-closure$(EXEEXT)
+@HAVE_GLIB_TRUE@am__EXEEXT_2 = hb-shape$(EXEEXT) hb-subset$(EXEEXT) \
+@HAVE_GLIB_TRUE@       hb-ot-shape-closure$(EXEEXT)
 am__installdirs = "$(DESTDIR)$(bindir)"
 PROGRAMS = $(bin_PROGRAMS)
 am__hb_ot_shape_closure_SOURCES_DIST = hb-ot-shape-closure.cc \
@@ -121,8 +118,7 @@ am__hb_ot_shape_closure_SOURCES_DIST = hb-ot-shape-closure.cc \
 am__objects_1 =
 am__objects_2 = hb-ot-shape-closure.$(OBJEXT) options.$(OBJEXT) \
        $(am__objects_1)
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am_hb_ot_shape_closure_OBJECTS =  \
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ $(am__objects_2)
+@HAVE_GLIB_TRUE@am_hb_ot_shape_closure_OBJECTS = $(am__objects_2)
 hb_ot_shape_closure_OBJECTS = $(am_hb_ot_shape_closure_OBJECTS)
 hb_ot_shape_closure_LDADD = $(LDADD)
 am__DEPENDENCIES_1 =
@@ -368,6 +364,8 @@ PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PTHREAD_CC = @PTHREAD_CC@
 PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -504,8 +502,11 @@ LDADD = \
 
 @HAVE_GLIB_TRUE@hb_shape_SOURCES = $(HB_SHAPE_sources)
 @HAVE_GLIB_TRUE@hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
-@HAVE_GLIB_TRUE@hb_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
-@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
+@HAVE_GLIB_TRUE@hb_subset_LDADD = \
+@HAVE_GLIB_TRUE@       $(LDADD) \
+@HAVE_GLIB_TRUE@       $(top_builddir)/src/libharfbuzz-subset.la
+
+@HAVE_GLIB_TRUE@hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
 all: all-am
 
 .SUFFIXES:
@@ -880,8 +881,9 @@ uninstall-am: uninstall-binPROGRAMS
 # Convenience targets:
 lib:
        @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+libs:
+       @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
 
-#if HAVE_OT
 #if HAVE_FONTCONFIG
 #hb_fc_list_SOURCES = \
 #      hb-fc.cc \
@@ -894,7 +896,6 @@ lib:
 #      $(NULL)
 #bin_PROGRAMS += hb-fc-list
 #endif # HAVE_FONTCONFIG
-#endif # HAVE_OT
 
 -include $(top_srcdir)/git.mk
 
index 0daee1f..49a0477 100644 (file)
@@ -71,10 +71,10 @@ struct color_t
 {
   static color_t from_ansi (unsigned int x)
   {
-    color_t c = {(0xFF<<24) | ((0xFF*(x&1))<<16) | ((0xFF*((x >> 1)&1))<<8) | (0xFF*((x >> 2)&1))};
+    color_t c = {(0xFFu<<24) | ((0xFFu*(x&1))<<16) | ((0xFFu*((x >> 1)&1))<<8) | (0xFFu*((x >> 2)&1))};
     return c;
   }
-  unsigned int to_ansi (void)
+  unsigned int to_ansi ()
   {
     return ((v >> 23) & 1) | ((v >> 14)&2) | ((v >> 5)&4);
   }
@@ -110,7 +110,7 @@ struct image_t
                own_data (true),
                data ((color_t *) malloc (sizeof (data[0]) * width * height)),
                stride (width) {}
-  ~image_t (void)
+  ~image_t ()
   { if (own_data) free (data); }
 
   color_t &operator () (unsigned int x, unsigned int y)
@@ -161,7 +161,7 @@ struct biimage_t
                height (height),
                bg (0), fg (0), unicolor (true),
                data ((uint8_t *) malloc (sizeof (data[0]) * width * height)) {}
-  ~biimage_t (void)
+  ~biimage_t ()
   { free (data); }
 
   void set (const image_t &image)
@@ -223,7 +223,7 @@ struct biimage_t
   uint8_t * const data;
 };
 
-const char *
+static const char *
 block_best (const biimage_t &bi, bool *inverse)
 {
   assert (bi.width  <= CELL_W);
index 1ea5b37..9640d89 100644 (file)
@@ -27,8 +27,7 @@
 #ifndef ANSI_PRINT_HH
 #define ANSI_PRINT_HH
 
-#include "hb-private.hh"
-#include <hb.h> /* for int types */
+#include "hb.hh"
 
 void
 ansi_print_image_rgb24 (const uint32_t *data,
index 337cd43..3ae3fa1 100644 (file)
@@ -83,10 +83,7 @@ struct output_buffer_t
     if (format.trace)
       hb_buffer_set_message_func (buffer, message_func, this, nullptr);
   }
-  void new_line (void)
-  {
-    line_no++;
-  }
+  void new_line () { line_no++; }
   void consume_text (hb_buffer_t  *buffer,
                     const char   *text,
                     unsigned int  text_len,
@@ -160,6 +157,34 @@ struct output_buffer_t
 int
 main (int argc, char **argv)
 {
+  if (argc == 2 && !strcmp (argv[1], "--batch"))
+  {
+    unsigned int ret = 0;
+    char buf[4092];
+    while (fgets (buf, sizeof (buf), stdin))
+    {
+      size_t l = strlen (buf);
+      if (l && buf[l - 1] == '\n') buf[l - 1] = '\0';
+      main_font_text_t<shape_consumer_t<output_buffer_t>, FONT_SIZE_UPEM, 0> driver;
+      char *args[32];
+      argc = 0;
+      char *p = buf, *e;
+      args[argc++] = p;
+      while ((e = strchr (p, ' ')) && argc < (int) (int) ARRAY_LENGTH (args))
+      {
+       *e++ = '\0';
+       while (*e == ' ')
+         e++;
+       args[argc++] = p = e;
+      }
+      ret |= driver.main (argc, args);
+      fflush (stdout);
+
+      if (ret)
+        break;
+    }
+    return ret;
+  }
   main_font_text_t<shape_consumer_t<output_buffer_t>, FONT_SIZE_UPEM, 0> driver;
   return driver.main (argc, argv);
 }
index 2061755..b7d9eb9 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "main-font-text.hh"
 #include "hb-subset.h"
-#include "hb-subset-private.hh"
 
 /*
  * Command line interface to the harfbuzz font subsetter.
@@ -90,19 +89,19 @@ struct subset_consumer_t
 
   void finish (const font_options_t *font_opts)
   {
-    input->drop_hints = subset_options.drop_hints;
+    hb_subset_input_set_drop_layout (input, !subset_options.keep_layout);
+    hb_subset_input_set_drop_hints (input, subset_options.drop_hints);
+    hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize);
 
-    hb_subset_profile_t *subset_profile = hb_subset_profile_create();
     hb_face_t *face = hb_font_get_face (font);
 
-    hb_face_t *new_face = hb_subset(face, subset_profile, input);
+    hb_face_t *new_face = hb_subset (face, input);
     hb_blob_t *result = hb_face_reference_blob (new_face);
 
     failed = !hb_blob_get_length (result);
     if (!failed)
       write_file (options.output_file, result);
 
-    hb_subset_profile_destroy (subset_profile);
     hb_subset_input_destroy (input);
     hb_blob_destroy (result);
     hb_face_destroy (new_face);
index ef75e6d..69a4c95 100644 (file)
@@ -30,7 +30,7 @@
 #include "view-cairo.hh"
 
 #define DEFAULT_FONT_SIZE 256
-#define SUBPIXEL_BITS 8
+#define SUBPIXEL_BITS 6
 
 int
 main (int argc, char **argv)
index cf18ea4..bc23132 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HELPER_CAIRO_ANSI_HH
 #define HELPER_CAIRO_ANSI_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include <cairo.h>
 
index b9f4985..b4f94a9 100644 (file)
@@ -64,11 +64,13 @@ _cairo_eps_surface_create_for_stream (cairo_write_func_t  write_func,
 
 static FT_Library ft_library;
 
+#ifdef HAVE_ATEXIT
 static inline
-void free_ft_library (void)
+void free_ft_library ()
 {
   FT_Done_FreeType (ft_library);
 }
+#endif
 
 cairo_scaled_font_t *
 helper_cairo_create_scaled_font (const font_options_t *font_opts)
@@ -89,10 +91,16 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
       atexit (free_ft_library);
 #endif
     }
-    FT_New_Face (ft_library,
-                font_opts->font_file,
-                font_opts->face_index,
-                &ft_face);
+
+    unsigned int blob_length;
+    const char *blob_data = hb_blob_get_data (font_opts->blob, &blob_length);
+
+    if (FT_New_Memory_Face (ft_library,
+                           (const FT_Byte *) blob_data,
+                            blob_length,
+                           font_opts->face_index,
+                           &ft_face))
+      fail (false, "FT_New_Memory_Face fail");
   }
   if (!ft_face)
   {
@@ -119,7 +127,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
     }
 #endif
 
-    cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+    cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags);
   }
   cairo_matrix_t ctm, font_matrix;
   cairo_font_options_t *font_options;
index 50bc0af..5bfbf7b 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HELPER_CAIRO_HH
 #define HELPER_CAIRO_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 #include "options.hh"
 
 #include <cairo.h>
@@ -60,7 +60,7 @@ struct helper_cairo_line_t {
   unsigned int num_clusters;
   cairo_text_cluster_flags_t cluster_flags;
 
-  void finish (void) {
+  void finish () {
     if (glyphs)
       cairo_glyph_free (glyphs);
     if (clusters)
index 3390371..36b654b 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_MAIN_FONT_TEXT_HH
 #define HB_MAIN_FONT_TEXT_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 #include "options.hh"
 
 /* main() body for utilities taking font and processing text.*/
@@ -50,7 +50,7 @@ locale_to_utf8 (char *s)
 template <typename consumer_t, int default_font_size, int subpixel_bits>
 struct main_font_text_t
 {
-  main_font_text_t (void)
+  main_font_text_t ()
                  : options ("[FONT-FILE] [TEXT]"),
                    font_opts (&options, default_font_size, subpixel_bits),
                    input (&options),
index 24dc41f..04ddcf6 100644 (file)
 #ifdef HAVE_FREETYPE
 #include <hb-ft.h>
 #endif
-#ifdef HAVE_OT
 #include <hb-ot.h>
-#endif
 
-struct supported_font_funcs_t {
+static struct supported_font_funcs_t {
        char name[4];
        void (*func) (hb_font_t *);
 } supported_font_funcs[] =
@@ -41,9 +39,7 @@ struct supported_font_funcs_t {
 #ifdef HAVE_FREETYPE
   {"ft",       hb_ft_font_set_funcs},
 #endif
-#ifdef HAVE_OT
   {"ot",       hb_ot_font_set_funcs},
-#endif
 };
 
 
@@ -66,7 +62,7 @@ fail (hb_bool_t suggest_help, const char *format, ...)
 
 
 static gchar *
-shapers_to_string (void)
+shapers_to_string ()
 {
   GString *shapers = g_string_new (nullptr);
   const char **shaper_list = hb_shape_list_shapers ();
@@ -99,7 +95,7 @@ show_version (const char *name G_GNUC_UNUSED,
 
 
 void
-option_parser_t::add_main_options (void)
+option_parser_t::add_main_options ()
 {
   GOptionEntry entries[] =
   {
@@ -172,9 +168,9 @@ parse_margin (const char *name G_GNUC_UNUSED,
   view_options_t *view_opts = (view_options_t *) data;
   view_options_t::margin_t &m = view_opts->margin;
   switch (sscanf (arg, "%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf", &m.t, &m.r, &m.b, &m.l)) {
-    case 1: m.r = m.t;
-    case 2: m.b = m.t;
-    case 3: m.l = m.r;
+    case 1: m.r = m.t; HB_FALLTHROUGH;
+    case 2: m.b = m.t; HB_FALLTHROUGH;
+    case 3: m.l = m.r; HB_FALLTHROUGH;
     case 4: return true;
     default:
       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
@@ -329,6 +325,7 @@ parse_text (const char *name G_GNUC_UNUSED,
     return false;
   }
 
+  text_opts->text_len = -1;
   text_opts->text = g_strdup (arg);
   return true;
 }
@@ -374,6 +371,7 @@ parse_unicodes (const char *name G_GNUC_UNUSED,
     s = p;
   }
 
+  text_opts->text_len = gs->len;
   text_opts->text = g_string_free (gs, FALSE);
   return true;
 }
@@ -415,11 +413,12 @@ shape_options_t::add_options (option_parser_t *parser)
     {"eot",            0, 0, G_OPTION_ARG_NONE,        &this->eot,                     "Treat text as end-of-paragraph",       nullptr},
     {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE,    &this->preserve_default_ignorables,     "Preserve Default-Ignorable characters",        nullptr},
     {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE,      &this->remove_default_ignorables,       "Remove Default-Ignorable characters",  nullptr},
+    {"invisible-glyph",        0, 0, G_OPTION_ARG_INT,         &this->invisible_glyph,         "Glyph value to replace Default-Ignorables with",       nullptr},
     {"utf8-clusters",  0, 0, G_OPTION_ARG_NONE,        &this->utf8_clusters,           "Use UTF8 byte indices, not char indices",      nullptr},
     {"cluster-level",  0, 0, G_OPTION_ARG_INT,         &this->cluster_level,           "Cluster merging level (default: 0)",   "0/1/2"},
     {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE,       &this->normalize_glyphs,        "Rearrange glyph clusters in nominal order",    nullptr},
     {"verify",         0, 0, G_OPTION_ARG_NONE,        &this->verify,                  "Perform sanity checks on shaping results",     nullptr},
-    {"num-iterations", 0, 0, G_OPTION_ARG_INT,         &this->num_iterations,          "Run shaper N times (default: 1)",      "N"},
+    {"num-iterations", 'n', 0, G_OPTION_ARG_INT,               &this->num_iterations,          "Run shaper N times (default: 1)",      "N"},
     {nullptr}
   };
   parser->add_group (entries,
@@ -489,7 +488,7 @@ parse_font_size (const char *name G_GNUC_UNUSED,
     return true;
   }
   switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->font_size_x, &font_opts->font_size_y)) {
-    case 1: font_opts->font_size_y = font_opts->font_size_x;
+    case 1: font_opts->font_size_y = font_opts->font_size_x; HB_FALLTHROUGH;
     case 2: return true;
     default:
       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
@@ -507,7 +506,7 @@ parse_font_ppem (const char *name G_GNUC_UNUSED,
 {
   font_options_t *font_opts = (font_options_t *) data;
   switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) {
-    case 1: font_opts->y_ppem = font_opts->x_ppem;
+    case 1: font_opts->y_ppem = font_opts->x_ppem; HB_FALLTHROUGH;
     case 2: return true;
     default:
       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
@@ -556,6 +555,7 @@ font_options_t::add_options (option_parser_t *parser)
     {"font-ppem",      0, 0, G_OPTION_ARG_CALLBACK,    (gpointer) &parse_font_ppem,    "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
     {"font-ptem",      0, 0, G_OPTION_ARG_DOUBLE,      &this->ptem,                    "Set font point-size (default: 0; disabled)",   "point-size"},
     {"font-funcs",     0, 0, G_OPTION_ARG_STRING,      &this->font_funcs,              text,                                           "impl"},
+    {"ft-load-flags",  0, 0, G_OPTION_ARG_INT,         &this->ft_load_flags,           "Set FreeType load-flags (default: 2)",         "integer"},
     {nullptr}
   };
   parser->add_group (entries,
@@ -638,39 +638,32 @@ output_options_t::add_options (option_parser_t *parser)
 
 
 hb_font_t *
-font_options_t::get_font (void) const
+font_options_t::get_font () const
 {
   if (font)
     return font;
 
-  hb_blob_t *blob = nullptr;
-
   /* Create the blob */
   if (!font_file)
     fail (true, "No font file set");
 
-  if (0 == strcmp (font_file, "-")) {
-    /* read it */
-    GString *gs = g_string_new (nullptr);
-    char buf[BUFSIZ];
+  const char *font_path = font_file;
+
+  if (0 == strcmp (font_path, "-"))
+  {
 #if defined(_WIN32) || defined(__CYGWIN__)
     setmode (fileno (stdin), O_BINARY);
+    font_path = "STDIN";
+#else
+    font_path = "/dev/stdin";
 #endif
-    while (!feof (stdin)) {
-      size_t ret = fread (buf, 1, sizeof (buf), stdin);
-      if (ferror (stdin))
-       fail (false, "Failed reading font from standard input: %s",
-             strerror (errno));
-      g_string_append_len (gs, buf, ret);
-    }
-    char *font_data = g_string_free (gs, false);
-    blob = hb_blob_create (font_data, gs->len,
-                          HB_MEMORY_MODE_WRITABLE, font_data,
-                          (hb_destroy_func_t) g_free);
-  } else {
-    blob = hb_blob_create_from_file (font_file);
   }
 
+  blob = hb_blob_create_from_file (font_path);
+
+  if (blob == hb_blob_get_empty ())
+    fail (false, "Couldn't read or find %s, or it was empty.", font_path);
+
   /* Create the face */
   hb_face_t *face = hb_face_create (blob, face_index);
   hb_blob_destroy (blob);
@@ -724,6 +717,9 @@ font_options_t::get_font (void) const
     }
   }
   set_font_funcs (font);
+#ifdef HAVE_FREETYPE
+  hb_ft_font_set_load_flags (font, ft_load_flags);
+#endif
 
   return font;
 }
@@ -733,7 +729,11 @@ const char *
 text_options_t::get_line (unsigned int *len)
 {
   if (text) {
-    if (!line) line = text;
+    if (!line)
+    {
+      line = text;
+      line_len = text_len;
+    }
     if (line_len == (unsigned int) -1)
       line_len = strlen (line);
 
@@ -795,7 +795,7 @@ text_options_t::get_line (unsigned int *len)
 
 
 FILE *
-output_options_t::get_file_handle (void)
+output_options_t::get_file_handle ()
 {
   if (fp)
     return fp;
@@ -975,7 +975,10 @@ subset_options_t::add_options (option_parser_t *parser)
 {
   GOptionEntry entries[] =
   {
+    {"layout", 0, 0, G_OPTION_ARG_NONE,  &this->keep_layout,   "Keep OpenType Layout tables",   nullptr},
     {"no-hinting", 0, 0, G_OPTION_ARG_NONE,  &this->drop_hints,   "Whether to drop hints",   nullptr},
+    {"desubroutinize", 0, 0, G_OPTION_ARG_NONE,  &this->desubroutinize,   "Remove CFF/CFF2 use of subroutines",   nullptr},
+
     {nullptr}
   };
   parser->add_group (entries,
index 8dfc842..e846258 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef OPTIONS_HH
 #define OPTIONS_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include <stdlib.h>
 #include <stddef.h>
@@ -46,9 +46,7 @@
 #endif
 
 #include <hb.h>
-#ifdef HAVE_OT
 #include <hb-ot.h>
-#endif
 #include <glib.h>
 #include <glib/gprintf.h>
 
@@ -56,16 +54,19 @@ void fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GN
 
 struct option_group_t
 {
+  virtual ~option_group_t () {}
+
   virtual void add_options (struct option_parser_t *parser) = 0;
 
-  virtual void pre_parse (GError **error G_GNUC_UNUSED) {};
-  virtual void post_parse (GError **error G_GNUC_UNUSED) {};
+  virtual void pre_parse (GError **error G_GNUC_UNUSED) {}
+  virtual void post_parse (GError **error G_GNUC_UNUSED) {}
 };
 
 
 struct option_parser_t
 {
-  option_parser_t (const char *usage) {
+  option_parser_t (const char *usage)
+  {
     memset (this, 0, sizeof (*this));
     usage_str = usage;
     context = g_option_context_new (usage);
@@ -73,13 +74,17 @@ struct option_parser_t
 
     add_main_options ();
   }
-  ~option_parser_t (void) {
+
+  static void _g_free_g_func (void *p, void * G_GNUC_UNUSED) { g_free (p); }
+
+  ~option_parser_t ()
+  {
     g_option_context_free (context);
-    g_ptr_array_foreach (to_free, (GFunc) g_free, nullptr);
+    g_ptr_array_foreach (to_free, _g_free_g_func, nullptr);
     g_ptr_array_free (to_free, TRUE);
   }
 
-  void add_main_options (void);
+  void add_main_options ();
 
   void add_group (GOptionEntry   *entries,
                  const gchar    *name,
@@ -93,7 +98,7 @@ struct option_parser_t
 
   void parse (int *argc, char ***argv);
 
-  G_GNUC_NORETURN void usage (void) {
+  G_GNUC_NORETURN void usage () {
     g_printerr ("Usage: %s [OPTION...] %s\n", g_get_prgname (), usage_str);
     exit (1);
   }
@@ -113,7 +118,8 @@ struct option_parser_t
 
 struct view_options_t : option_group_t
 {
-  view_options_t (option_parser_t *parser) {
+  view_options_t (option_parser_t *parser)
+  {
     annotate = false;
     fore = nullptr;
     back = nullptr;
@@ -122,7 +128,7 @@ struct view_options_t : option_group_t
 
     add_options (parser);
   }
-  ~view_options_t (void)
+  virtual ~view_options_t ()
   {
     g_free (fore);
     g_free (back);
@@ -150,6 +156,7 @@ struct shape_options_t : option_group_t
     num_features = 0;
     shapers = nullptr;
     utf8_clusters = false;
+    invisible_glyph = 0;
     cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
     normalize_glyphs = false;
     verify = false;
@@ -157,7 +164,7 @@ struct shape_options_t : option_group_t
 
     add_options (parser);
   }
-  ~shape_options_t (void)
+  virtual ~shape_options_t ()
   {
     g_free (direction);
     g_free (language);
@@ -180,6 +187,7 @@ struct shape_options_t : option_group_t
                                  (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) |
                                  (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) |
                                  0));
+    hb_buffer_set_invisible_glyph (buffer, invisible_glyph);
     hb_buffer_set_cluster_level (buffer, cluster_level);
     hb_buffer_guess_segment_properties (buffer);
   }
@@ -430,6 +438,7 @@ struct shape_options_t : option_group_t
   unsigned int num_features;
   char **shapers;
   hb_bool_t utf8_clusters;
+  hb_codepoint_t invisible_glyph;
   hb_buffer_cluster_level_t cluster_level;
   hb_bool_t normalize_glyphs;
   hb_bool_t verify;
@@ -454,12 +463,15 @@ struct font_options_t : option_group_t
     face_index = 0;
     font_size_x = font_size_y = default_font_size;
     font_funcs = nullptr;
+    ft_load_flags = 2;
 
+    blob = nullptr;
     font = nullptr;
 
     add_options (parser);
   }
-  ~font_options_t (void) {
+  virtual ~font_options_t ()
+  {
     g_free (font_file);
     free (variations);
     g_free (font_funcs);
@@ -468,9 +480,10 @@ struct font_options_t : option_group_t
 
   void add_options (option_parser_t *parser);
 
-  hb_font_t *get_font (void) const;
+  hb_font_t *get_font () const;
 
   char *font_file;
+  mutable hb_blob_t *blob;
   int face_index;
   hb_variation_t *variations;
   unsigned int num_variations;
@@ -482,6 +495,7 @@ struct font_options_t : option_group_t
   mutable double font_size_x;
   mutable double font_size_y;
   char *font_funcs;
+  int ft_load_flags;
 
   private:
   mutable hb_font_t *font;
@@ -490,10 +504,12 @@ struct font_options_t : option_group_t
 
 struct text_options_t : option_group_t
 {
-  text_options_t (option_parser_t *parser) {
+  text_options_t (option_parser_t *parser)
+  {
     text_before = nullptr;
     text_after = nullptr;
 
+    text_len = -1;
     text = nullptr;
     text_file = nullptr;
 
@@ -504,14 +520,15 @@ struct text_options_t : option_group_t
 
     add_options (parser);
   }
-  ~text_options_t (void) {
+  virtual ~text_options_t ()
+  {
     g_free (text_before);
     g_free (text_after);
     g_free (text);
     g_free (text_file);
     if (gs)
       g_string_free (gs, true);
-    if (fp)
+    if (fp && fp != stdin)
       fclose (fp);
   }
 
@@ -522,13 +539,14 @@ struct text_options_t : option_group_t
       g_set_error (error,
                   G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
                   "Only one of text and text-file can be set");
-  };
+  }
 
   const char *get_line (unsigned int *len);
 
   char *text_before;
   char *text_after;
 
+  int text_len;
   char *text;
   char *text_file;
 
@@ -542,7 +560,8 @@ struct text_options_t : option_group_t
 struct output_options_t : option_group_t
 {
   output_options_t (option_parser_t *parser,
-                   const char **supported_formats_ = nullptr) {
+                   const char **supported_formats_ = nullptr)
+  {
     output_file = nullptr;
     output_format = nullptr;
     supported_formats = supported_formats_;
@@ -552,10 +571,11 @@ struct output_options_t : option_group_t
 
     add_options (parser);
   }
-  ~output_options_t (void) {
+  virtual ~output_options_t ()
+  {
     g_free (output_file);
     g_free (output_format);
-    if (fp)
+    if (fp && fp != stdout)
       fclose (fp);
   }
 
@@ -571,7 +591,7 @@ struct output_options_t : option_group_t
       if (output_format)
       {
          output_format++; /* skip the dot */
-         output_format = strdup (output_format);
+         output_format = g_strdup (output_format);
       }
     }
 
@@ -579,7 +599,7 @@ struct output_options_t : option_group_t
       output_file = nullptr; /* STDOUT */
   }
 
-  FILE *get_file_handle (void);
+  FILE *get_file_handle ();
 
   char *output_file;
   char *output_format;
@@ -653,14 +673,18 @@ struct subset_options_t : option_group_t
 {
   subset_options_t (option_parser_t *parser)
   {
+    keep_layout = false;
     drop_hints = false;
+    desubroutinize = false;
 
     add_options (parser);
   }
 
   void add_options (option_parser_t *parser);
 
+  hb_bool_t keep_layout;
   hb_bool_t drop_hints;
+  hb_bool_t desubroutinize;
 };
 
 /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
index fa419f1..da0d880 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef HB_SHAPE_CONSUMER_HH
 #define HB_SHAPE_CONSUMER_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 #include "options.hh"
 
 
index 00df68c..1f51f0e 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef VIEW_CAIRO_HH
 #define VIEW_CAIRO_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 #include "options.hh"
 #include "helper-cairo.hh"
 
@@ -39,28 +39,22 @@ struct view_cairo_t
                 view_options (parser),
                 direction (HB_DIRECTION_INVALID),
                 lines (0), scale_bits (0) {}
-  ~view_cairo_t (void) {
+  ~view_cairo_t () {
     cairo_debug_reset_static_data ();
   }
 
   void init (hb_buffer_t *buffer, const font_options_t *font_opts)
   {
     lines = g_array_new (false, false, sizeof (helper_cairo_line_t));
-    scale_bits = -font_opts->subpixel_bits;
-  }
-  void new_line (void)
-  {
+    scale_bits = - (int) font_opts->subpixel_bits;
   }
+  void new_line () {}
   void consume_text (hb_buffer_t  *buffer,
                     const char   *text,
                     unsigned int  text_len,
-                    hb_bool_t     utf8_clusters)
-  {
-  }
+                    hb_bool_t     utf8_clusters) {}
   void error (const char *message)
-  {
-    g_printerr ("%s: %s\n", g_get_prgname (), message);
-  }
+  { g_printerr ("%s: %s\n", g_get_prgname (), message); }
   void consume_glyphs (hb_buffer_t  *buffer,
                       const char   *text,
                       unsigned int  text_len,